Andrzej Krzemienski wrote:
I am interested in the latter ("Otherwise") case, so, going to emplace:
template<size_t I, class... A> constexpr variant_alternative_t<I, variant<T...>>& emplace( A&&... a );
- Requires: I < sizeof(T…).
Effects: Destroys the currently contained value, then initializes a new contained value as if using the expression Ti(std::forward<A>(a)…).
This doesn't mention any double buffering. No tricks, no "monostate". It reads as if the variant is left with no contained object whatsoever.
Yes, we mentioned that upthread. At minimum, I'll need to add Remarks that on exception, the variant is left in a valid but unspecified state. Rigorously specifying the exact behavior of emplace will be rather verbose, and I'm not yet sure how to go about it. What's important about the assignment guarantees is this:
noexcept( mp_all<std::is_nothrow_copy_constructible<T>..., std::is_nothrow_copy_assignable<T>...>::value );
or, more practically, this:
constexpr variant& operator=( variant&& r ) noexcept( mp_all<std::is_nothrow_move_constructible<T>..., std::is_nothrow_move_assignable<T>...>::value );
That is, the way to achieve the strong guarantee on assignment is to have all type nothrow moveable, and then using v1= V(v2);