20 General utilities library [utilities]

20.7 Variants [variant]

20.7.2 Class template variant [variant.variant]

20.7.2.3 Assignment [variant.assign]

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() == rhs.index(), assigns the value contained in rhs to the value contained in *this. Otherwise,

  • copies the value contained in rhs to a temporary, then destroys any value contained in *this. Sets *this to hold the same alternative index as rhs and initializes the value contained in *this as if direct-non-list-initializing an object of type Tj with std::forward<Tj>(TMP), with TMP being the temporary and j being rhs.index().

Returns: *this.

Postconditions: index() == rhs.index().

Remarks: This function shall not participate in overload resolution unless is_copy_constructible_v<Ti> && is_move_constructible_v<Ti> && is_copy_assignable_v<Ti> is true for all i.

  • If an exception is thrown during the call to Tj's copy assignment, the state of the contained value is as defined by the exception safety guarantee of Tj's copy assignment; index() will be j.

  • If an exception is thrown during the call to Tj's copy construction (with j being rhs.index()), *this will remain unchanged.

  • If an exception is thrown during the call to Tj's move construction, the variant will hold no value.

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() == rhs.index(), assigns get<j>(std::move(rhs)) to the value contained in *this, with j being index(). Otherwise,

  • destroys any value contained in *this. Sets *this to hold the same alternative index as rhs and initializes the value contained in *this as if direct-non-list-initializing an object of type Tj with get<j>(std::move(rhs)) with j being rhs.index().

Returns: *this.

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, destroys any value contained in *this, sets *this to hold the alternative type Tj as selected by the imaginary function overload resolution described above, and direct-initializes the contained value as if direct-non-list-initializing it with std::forward<T>(t).

Postconditions: holds_alternative<Tj>(*this) is true, with Tj selected by the imaginary function overload resolution described above.

Returns: *this.

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.