May I change the held type in a std::variant from within a call to std::visit
Does the following code invoke undefined behaviour?
std::variant<A,B> v = ...;
std::visit([&v](auto& e){
if constexpr (std::is_same_v<std::remove_reference_t<decltype(e)>,A>)
e.some_modifying_operation_on_A();
else {
int i = e.some_accessor_of_B();
v = some_function_returning_A(i);
}
}, v);
In particular, when the variant does not contain an A
,
this code re-assigns an A
while still holding a reference to the previously held object of type B
.
However, because the reference is not used anymore after the assignment,
I feel the code is fine.
However, would a standard-library be free to implement std::visit
in a way such that the above is undefined behaviour?
c++ c++17 std-variant
add a comment |
Does the following code invoke undefined behaviour?
std::variant<A,B> v = ...;
std::visit([&v](auto& e){
if constexpr (std::is_same_v<std::remove_reference_t<decltype(e)>,A>)
e.some_modifying_operation_on_A();
else {
int i = e.some_accessor_of_B();
v = some_function_returning_A(i);
}
}, v);
In particular, when the variant does not contain an A
,
this code re-assigns an A
while still holding a reference to the previously held object of type B
.
However, because the reference is not used anymore after the assignment,
I feel the code is fine.
However, would a standard-library be free to implement std::visit
in a way such that the above is undefined behaviour?
c++ c++17 std-variant
5
Do you want quotes from the standard to back up the answer(s) you get?
– NathanOliver
7 hours ago
1
From looking at [variant.visit], I'm 99% sure this code is compliant and guaranteed not to have UB, sincestd::visit(vis, variant)
should be equivalent tovis(get</* active member */>(variant))
, but I'm not confident enough in reading the standard to be certain
– Justin
6 hours ago
@NathanOliver: I don't need actual quotes from the standard, as long as the experts here can agree on the answer:-).
– burnpanck
6 hours ago
add a comment |
Does the following code invoke undefined behaviour?
std::variant<A,B> v = ...;
std::visit([&v](auto& e){
if constexpr (std::is_same_v<std::remove_reference_t<decltype(e)>,A>)
e.some_modifying_operation_on_A();
else {
int i = e.some_accessor_of_B();
v = some_function_returning_A(i);
}
}, v);
In particular, when the variant does not contain an A
,
this code re-assigns an A
while still holding a reference to the previously held object of type B
.
However, because the reference is not used anymore after the assignment,
I feel the code is fine.
However, would a standard-library be free to implement std::visit
in a way such that the above is undefined behaviour?
c++ c++17 std-variant
Does the following code invoke undefined behaviour?
std::variant<A,B> v = ...;
std::visit([&v](auto& e){
if constexpr (std::is_same_v<std::remove_reference_t<decltype(e)>,A>)
e.some_modifying_operation_on_A();
else {
int i = e.some_accessor_of_B();
v = some_function_returning_A(i);
}
}, v);
In particular, when the variant does not contain an A
,
this code re-assigns an A
while still holding a reference to the previously held object of type B
.
However, because the reference is not used anymore after the assignment,
I feel the code is fine.
However, would a standard-library be free to implement std::visit
in a way such that the above is undefined behaviour?
c++ c++17 std-variant
c++ c++17 std-variant
edited 6 hours ago
Barry
184k21324595
184k21324595
asked 7 hours ago
burnpanckburnpanck
1,136622
1,136622
5
Do you want quotes from the standard to back up the answer(s) you get?
– NathanOliver
7 hours ago
1
From looking at [variant.visit], I'm 99% sure this code is compliant and guaranteed not to have UB, sincestd::visit(vis, variant)
should be equivalent tovis(get</* active member */>(variant))
, but I'm not confident enough in reading the standard to be certain
– Justin
6 hours ago
@NathanOliver: I don't need actual quotes from the standard, as long as the experts here can agree on the answer:-).
– burnpanck
6 hours ago
add a comment |
5
Do you want quotes from the standard to back up the answer(s) you get?
– NathanOliver
7 hours ago
1
From looking at [variant.visit], I'm 99% sure this code is compliant and guaranteed not to have UB, sincestd::visit(vis, variant)
should be equivalent tovis(get</* active member */>(variant))
, but I'm not confident enough in reading the standard to be certain
– Justin
6 hours ago
@NathanOliver: I don't need actual quotes from the standard, as long as the experts here can agree on the answer:-).
– burnpanck
6 hours ago
5
5
Do you want quotes from the standard to back up the answer(s) you get?
– NathanOliver
7 hours ago
Do you want quotes from the standard to back up the answer(s) you get?
– NathanOliver
7 hours ago
1
1
From looking at [variant.visit], I'm 99% sure this code is compliant and guaranteed not to have UB, since
std::visit(vis, variant)
should be equivalent to vis(get</* active member */>(variant))
, but I'm not confident enough in reading the standard to be certain– Justin
6 hours ago
From looking at [variant.visit], I'm 99% sure this code is compliant and guaranteed not to have UB, since
std::visit(vis, variant)
should be equivalent to vis(get</* active member */>(variant))
, but I'm not confident enough in reading the standard to be certain– Justin
6 hours ago
@NathanOliver: I don't need actual quotes from the standard, as long as the experts here can agree on the answer:-).
– burnpanck
6 hours ago
@NathanOliver: I don't need actual quotes from the standard, as long as the experts here can agree on the answer:-).
– burnpanck
6 hours ago
add a comment |
1 Answer
1
active
oldest
votes
The code is fine.
There is no requirement in the specification of std::visit
that the visitor not change the alternative of any of the variants it is invoked on. The only requirement is:
Requires: For each valid pack
m
,e(m)
shall be a valid expression. All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.
Your visitor is a valid expression for each m
and always returns void
, so it satisfies the requirements and has well-defined behavior.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55187548%2fmay-i-change-the-held-type-in-a-stdvariant-from-within-a-call-to-stdvisit%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The code is fine.
There is no requirement in the specification of std::visit
that the visitor not change the alternative of any of the variants it is invoked on. The only requirement is:
Requires: For each valid pack
m
,e(m)
shall be a valid expression. All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.
Your visitor is a valid expression for each m
and always returns void
, so it satisfies the requirements and has well-defined behavior.
add a comment |
The code is fine.
There is no requirement in the specification of std::visit
that the visitor not change the alternative of any of the variants it is invoked on. The only requirement is:
Requires: For each valid pack
m
,e(m)
shall be a valid expression. All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.
Your visitor is a valid expression for each m
and always returns void
, so it satisfies the requirements and has well-defined behavior.
add a comment |
The code is fine.
There is no requirement in the specification of std::visit
that the visitor not change the alternative of any of the variants it is invoked on. The only requirement is:
Requires: For each valid pack
m
,e(m)
shall be a valid expression. All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.
Your visitor is a valid expression for each m
and always returns void
, so it satisfies the requirements and has well-defined behavior.
The code is fine.
There is no requirement in the specification of std::visit
that the visitor not change the alternative of any of the variants it is invoked on. The only requirement is:
Requires: For each valid pack
m
,e(m)
shall be a valid expression. All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.
Your visitor is a valid expression for each m
and always returns void
, so it satisfies the requirements and has well-defined behavior.
answered 6 hours ago
BarryBarry
184k21324595
184k21324595
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55187548%2fmay-i-change-the-held-type-in-a-stdvariant-from-within-a-call-to-stdvisit%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
Do you want quotes from the standard to back up the answer(s) you get?
– NathanOliver
7 hours ago
1
From looking at [variant.visit], I'm 99% sure this code is compliant and guaranteed not to have UB, since
std::visit(vis, variant)
should be equivalent tovis(get</* active member */>(variant))
, but I'm not confident enough in reading the standard to be certain– Justin
6 hours ago
@NathanOliver: I don't need actual quotes from the standard, as long as the experts here can agree on the answer:-).
– burnpanck
6 hours ago