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<T> or !is_­nothrow_­move_­constructible_­v<T> 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<T> && is_­copy_­assignable_­v<T> 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<T> && is_­move_­assignable_­v<T> is true for all i.
The expression inside noexcept is equivalent to: is_­nothrow_­move_­constructible_­v<T> && is_­nothrow_­move_­assignable_­v<T> for all i.
  • If an exception is thrown during the call to T's move construction (with j being rhs.index()), the variant will hold no value.
  • If an exception is thrown during the call to T's move assignment, the state of the contained value is as defined by the exception safety guarantee of T's move assignment; index() will be j.
template <class T> variant& operator=(T&& t) noexcept(see below);
Let T be a type that is determined as follows: build an imaginary function FUN(T) for each alternative type T.
The overload FUN(T) selected by overload resolution for the expression FUN(std​::​forward<T>(​t)) defines the alternative T which is the type of the contained value after assignment.
Effects:
  • If *this holds a T, assigns std​::​forward<T>(t) to the value contained in *this.
    Otherwise,
  • if is_­nothrow_­constructible_­v<T, T> || !is_­nothrow_­move_­constructible_­v<T> is true, equivalent to emplace<j>(std​::​forward<T>(t)).
    Otherwise,
  • equivalent to operator=(variant(std​::​forward<T>(t))).
Postconditions: holds_­alternative<T>(*this) is true, with T 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<T&, T> && is_­constructible_­v<T, 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<T&, T> && is_nothrow_constructible_v<T, 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.