variant& operator=(const variant& rhs);
Effects:
If neither *this nor rhs holds a value, there is no effect. Otherwise,
if *this holds a value but rhs does not, destroys the value contained in *this and sets *this to not hold a value. Otherwise,
if index() == j, assigns the value contained in rhs to the value contained in *this. Otherwise,
if either is_nothrow_copy_constructible_v<Tj> or !is_nothrow_move_constructible_v<Tj> is true, equivalent to emplace<j>(get<j>(rhs)). Otherwise,
equivalent to operator=(variant(rhs)).
Remarks: This function shall not participate in overload resolution unless is_copy_constructible_v<Ti> && is_copy_assignable_v<Ti> is true for all i.
variant& operator=(variant&& rhs) noexcept(see below);
Effects:
If neither *this nor rhs holds a value, there is no effect. Otherwise,
if *this holds a value but rhs does not, destroys the value contained in *this and sets *this to not hold a value. Otherwise,
if index() == j, assigns get<j>(std::move(rhs)) to the value contained in *this. Otherwise,
equivalent to emplace<j>(get<j>(std::move(rhs))).
Remarks: This function shall not participate in overload resolution unless is_move_constructible_v<Ti> && is_move_assignable_v<Ti> is true for all i. The expression inside noexcept is equivalent to: is_nothrow_move_constructible_v<Ti> && is_nothrow_move_assignable_v<Ti> for all i.
If an exception is thrown during the call to Tj's move construction (with j being rhs.index()), the variant will hold no value.
If an exception is thrown during the call to Tj's move assignment, the state of the contained value is as defined by the exception safety guarantee of Tj's move assignment; index() will be j.
template <class T> variant& operator=(T&& t) noexcept(see below);
Let Tj be a type that is determined as follows: build an imaginary function FUN(Ti) for each alternative type Ti. The overload FUN(Tj) selected by overload resolution for the expression FUN(std::forward<T>(t)) defines the alternative Tj which is the type of the contained value after assignment.
Effects:
If *this holds a Tj, assigns std::forward<T>(t) to the value contained in *this. Otherwise,
if is_nothrow_constructible_v<Tj, T> || !is_nothrow_move_constructible_v<Tj> is true, equivalent to emplace<j>(std::forward<T>(t)). Otherwise,
equivalent to operator=(variant(std::forward<T>(t))).
Postconditions: holds_alternative<Tj>(*this) is true, with Tj selected by the imaginary function overload resolution described above.
Remarks: This function shall not participate in overload resolution unless is_same_v<decay_t<T>, variant> is false, unless is_assignable_v<Tj&, T> && is_constructible_v<Tj, T> is true, and unless the expression FUN(std::forward<T>(t)) (with FUN being the above-mentioned set of imaginary functions) is well formed.
[ Note:
variant<string, string> v; v = "abc";
is ill-formed, as both alternative types have an equally viable constructor for the argument. — end note ]
The expression inside noexcept is equivalent to:
is_nothrow_assignable_v<Tj&, T> && is_nothrow_constructible_v<Tj, T>
If an exception is thrown during the assignment of std::forward<T>(t) to the value contained in *this, the state of the contained value and t are as defined by the exception safety guarantee of the assignment expression; valueless_by_exception() will be false.
If an exception is thrown during the initialization of the contained value, the variant object might not hold a value.