问题
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?
回答1:
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.
来源:https://stackoverflow.com/questions/55187548/may-i-change-the-held-type-in-a-stdvariant-from-within-a-call-to-stdvisit