23 General utilities library [utilities]

23.7 Variants [variant]

23.7.3 Class template variant [variant.variant]

23.7.3.3 Assignment [variant.assign]

variant& operator=(const variant& rhs);

Let j be rhs.index().

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)).

Returns: *this.

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

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);

Let j be rhs.index().

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))).

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,

  • 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.

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.