Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

May I change the held type in a std::variant from within a call to std::visit

Tags:

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?

like image 701
burnpanck Avatar asked Mar 15 '19 17:03

burnpanck


1 Answers

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.

like image 114
Barry Avatar answered Oct 18 '22 11:10

Barry