[variant.variant] (original) (raw)
22 General utilities library [utilities]
22.6 Variants [variant]
22.6.3 Class template variant [variant.variant]
22.6.3.1 General [variant.variant.general]
22.6.3.2 Constructors [variant.ctor]
22.6.3.3 Destructor [variant.dtor]
22.6.3.4 Assignment [variant.assign]
22.6.3.5 Modifiers [variant.mod]
22.6.3.6 Value status [variant.status]
22.6.3.7 Swap [variant.swap]
22.6.3.1 General [variant.variant.general]
namespace std { template<class... Types> class variant { public: constexpr variant() noexcept(see below);constexpr variant(const variant&);constexpr variant(variant&&) noexcept(see below);template<class T> constexpr variant(T&&) noexcept(see below);template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&...);template<class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U>, Args&&...);template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&...);template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U>, Args&&...);constexpr ~variant();constexpr variant& operator=(const variant&);constexpr variant& operator=(variant&&) noexcept(see below);template<class T> constexpr variant& operator=(T&&) noexcept(see below);template<class T, class... Args> constexpr T& emplace(Args&&...);template<class T, class U, class... Args> constexpr T& emplace(initializer_list<U>, Args&&...);template<size_t I, class... Args> constexpr variant_alternative_t<I, variant<Types...>>& emplace(Args&&...);template<size_t I, class U, class... Args> constexpr variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U>, Args&&...);constexpr bool valueless_by_exception() const noexcept;constexpr size_t index() const noexcept;constexpr void swap(variant&) noexcept(see below);template<class Self, class Visitor> constexpr decltype(auto) visit(this Self&&, Visitor&&);template<class R, class Self, class Visitor> constexpr R visit(this Self&&, Visitor&&);};}
Any instance of variant at any given time either holds a value of one of its alternative types or holds no value.
When an instance of variant holds a value of alternative type T, it means that a value of type T, referred to as the variantobject's contained value, is nested within ([intro.object]) thevariant object.
A program that instantiates the definition of variant with no template arguments is ill-formed.
If a program declares an explicit or partial specialization of variant, the program is ill-formed, no diagnostic required.
22.6.3.2 Constructors [variant.ctor]
In the descriptions that follow, let i be in the range [0, sizeof...(Types)), and be the type in Types.
constexpr variant() noexcept(_see below_);
Constraints: is_default_constructible_v<> is true.
Effects: Constructs a variant holding a value-initialized value of type .
Postconditions: valueless_by_exception() is false and index() is 0.
Throws: Any exception thrown by the value-initialization of .
Remarks: This function is constexpr if and only if the value-initialization of the alternative type would be constexpr-suitable ([dcl.constexpr]).
The exception specification is equivalent tois_nothrow_default_constructible_v<>.
[Note 1:
See also class monostate.
— _end note_]
constexpr variant(const variant& w);
Effects: If w holds a value, initializes the variant to hold the same alternative as w and direct-initializes the contained value with GET<j>(w), where j is w.index().
Otherwise, initializes the variant to not hold a value.
Throws: Any exception thrown by direct-initializing any for all i.
Remarks: This constructor is defined as deleted unlessis_copy_constructible_v<> is true for all i.
If is_trivially_copy_constructible_v<>is true for all i, this constructor is trivial.
constexpr variant(variant&& w) noexcept(_see below_);
Constraints: is_move_constructible_v<> is true for all i.
Effects: If w holds a value, initializes the variant to hold the same alternative as w and direct-initializes the contained value with_GET_<j>(std::move(w)), where j is w.index().
Otherwise, initializes the variant to not hold a value.
Throws: Any exception thrown by move-constructing any for all i.
Remarks: The exception specification is equivalent to the logical and ofis_nothrow_move_constructible_v<> for all i.
If is_trivially_move_constructible_v<>is true for all i, this constructor is trivial.
template<class T> constexpr variant(T&& t) noexcept(_see below_);
Let be a type that is determined as follows: build an imaginary function FUN()for each alternative type for which x[] = {std::forward<T>(t)};is well-formed for some invented variable x.
The overload FUN() selected by overload resolution for the expression FUN(std::forward<T>(t)) defines the alternative which is the type of the contained value after construction.
Constraints:
- sizeof...(Types) is nonzero,
- is_same_v<remove_cvref_t<T>, variant> is false,
- remove_cvref_t<T> is neither a specialization of in_place_type_t nor a specialization of in_place_index_t,
- is_constructible_v<, T> is true, and
- the expression FUN(std::forward<T>(t))(with FUN being the above-mentioned set of imaginary functions) is well-formed.
[Note 2:
variant<string, string> v("abc");is ill-formed, as both alternative types have an equally viable constructor for the argument.
— _end note_]
Effects: Initializes *this to hold the alternative type and direct-non-list-initializes the contained value with std::forward<T>(t).
Postconditions: holds_alternative<>(*this) is true.
Throws: Any exception thrown by the initialization of the selected alternative .
Remarks: The exception specification is equivalent tois_nothrow_constructible_v<, T>.
If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
Constraints:
- There is exactly one occurrence of T in Types... and
- is_constructible_v<T, Args...> is true.
Effects: Direct-non-list-initializes the contained value of type Twith std::forward<Args>(args)....
Postconditions: holds_alternative<T>(*this) is true.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Constraints:
- There is exactly one occurrence of T in Types... and
- is_constructible_v<T, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes the contained value of type Twith il, std::forward<Args>(args)....
Postconditions: holds_alternative<T>(*this) is true.
Throws: Any exception thrown by calling the selected constructor of T.
Remarks: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
Constraints:
- I is less than sizeof...(Types) and
- is_constructible_v<, Args...> is true.
Effects: Direct-non-list-initializes the contained value of type with std::forward<Args>(args)....
Postconditions: index() is I.
Throws: Any exception thrown by calling the selected constructor of .
Remarks: If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
template<size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);
Constraints:
- I is less than sizeof...(Types) and
- is_constructible_v<, initializer_list<U>&, Args...> is true.
Effects: Direct-non-list-initializes the contained value of type with il, std::forward<Args>(args)....
Postconditions: index() is I.
Remarks: If 's selected constructor is a constexpr constructor, this constructor is a constexpr constructor.
22.6.3.3 Destructor [variant.dtor]
Effects: If valueless_by_exception() is false, destroys the currently contained value.
Remarks: If is_trivially_destructible_v<> is true for all , then this destructor is trivial.
22.6.3.4 Assignment [variant.assign]
constexpr 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 rhsto the value contained in *this.
- Otherwise, if either is_nothrow_copy_constructible_v<>is true oris_nothrow_move_constructible_v<> is false, equivalent to emplace<j>(GET<j>(rhs)).
- Otherwise, equivalent to operator=(variant(rhs)).
Postconditions: index() == rhs.index().
Remarks: This operator is defined as deleted unlessis_copy_constructible_v<> && is_copy_assignable_v<>is true for all i.
If is_trivially_copy_constructible_v<> && is_trivially_copy_assignable_v<> && is_trivially_destructible_v<>is true for all i, this assignment operator is trivial.
constexpr variant& operator=(variant&& rhs) noexcept(_see below_);
Constraints: is_move_constructible_v<> && is_move_assignable_v<> istrue for all i.
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: If is_trivially_move_constructible_v<> && is_trivially_move_assignable_v<> && is_trivially_destructible_v<>is true for all i, this assignment operator is trivial.
The exception specification is equivalent tois_nothrow_move_constructible_v<> && is_nothrow_move_assignable_v<> for all i.
- If an exception is thrown during the call to 's move construction (with j being rhs.index()), the variant will hold no value.
- If an exception is thrown during the call to 's move assignment, the state of the contained value is as defined by the exception safety guarantee of 's move assignment; index() will be j.
template<class T> constexpr variant& operator=(T&& t) noexcept(_see below_);
Let be a type that is determined as follows: build an imaginary function FUN()for each alternative type for which x[] = {std::forward<T>(t)};is well-formed for some invented variable x.
The overload FUN() selected by overload resolution for the expression FUN(std::forward<T>(t)) defines the alternative which is the type of the contained value after assignment.
Constraints:
- is_same_v<remove_cvref_t<T>, variant> is false,
- is_assignable_v<&, T> && is_constructible_v<, T>is true, and
- the expression FUN(std::forward<T>(t))(with FUN being the above-mentioned set of imaginary functions) is well-formed.
[Note 1:
variant<string, string> v; v = "abc";is ill-formed, as both alternative types have an equally viable constructor for the argument.
— _end note_]
Effects:
- If *this holds a , assigns std::forward<T>(t) to the value contained in *this.
- Otherwise, if is_nothrow_constructible_v<, T> || !is_nothrow_move_constructible_v<> is true, equivalent to emplace<j>(std::forward<T>(t)).
- Otherwise, equivalent to emplace<j>((std::forward<T>(t))).
Postconditions: holds_alternative<>(*this) is true, with selected by the imaginary function overload resolution described above.
Remarks: The exception specification 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 andt 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 is permitted to not hold a value.
22.6.3.5 Modifiers [variant.mod]
template<class T, class... Args> constexpr T& emplace(Args&&... args);
Constraints: is_constructible_v<T, Args...> is true, andT occurs exactly once in Types.
Effects: Equivalent to:return emplace<I>(std::forward<Args>(args)...);where I is the zero-based index of T in Types.
template<class T, class U, class... Args> constexpr T& emplace(initializer_list<U> il, Args&&... args);
Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true, and T occurs exactly once in Types.
Effects: Equivalent to:return emplace<I>(il, std::forward<Args>(args)...);where I is the zero-based index of T in Types.
template<size_t I, class... Args> constexpr variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
Mandates: I < sizeof...(Types).
Constraints: is_constructible_v<, Args...> is true.
Effects: Destroys the currently contained value if valueless_by_exception()is false.
Then direct-non-list-initializes the contained value of type with the arguments std::forward<Args>(args)....
Postconditions: index() is I.
Returns: A reference to the new contained value.
Throws: Any exception thrown during the initialization of the contained value.
Remarks: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value.
template<size_t I, class U, class... Args> constexpr variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args);
Mandates: I < sizeof...(Types).
Constraints: is_constructible_v<, initializer_list<U>&, Args...> is true.
Effects: Destroys the currently contained value if valueless_by_exception()is false.
Then direct-non-list-initializes the contained value of type with il, std::forward<Args>(args)....
Postconditions: index() is I.
Returns: A reference to the new contained value.
Throws: Any exception thrown during the initialization of the contained value.
Remarks: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value.
22.6.3.6 Value status [variant.status]
constexpr bool valueless_by_exception() const noexcept;
Effects: Returns false if and only if the variant holds a value.
[Note 1:
It is possible for a variant to hold no value if an exception is thrown during a type-changing assignment or emplacement.
The latter means that even avariant<float, int> can become valueless_by_exception(), for instance bystruct S { operator int() { throw 42; }}; variant<float, int> v{12.f}; v.emplace<1>(S());
— _end note_]
constexpr size_t index() const noexcept;
Effects: If valueless_by_exception() is true, returns variant_npos.
Otherwise, returns the zero-based index of the alternative of the contained value.
22.6.3.7 Swap [variant.swap]
constexpr void swap(variant& rhs) noexcept(_see below_);
Mandates: is_move_constructible_v<> is true for all i.
Effects:
- If valueless_by_exception() && rhs.valueless_by_exception() no effect.
- Otherwise, if index() == rhs.index(), calls swap(GET<i>(*this), GET<i>(rhs)) where i is index().
- Otherwise, exchanges values of rhs and *this.
Throws: If index() == rhs.index(), any exception thrown by swap(GET<i>(*this), GET<i>(rhs))with i being index().
Otherwise, any exception thrown by the move constructor of or with i being index() and j being rhs.index().
Remarks: If an exception is thrown during the call to function swap(GET<i>(*this), GET<i>(rhs)), the states of the contained values of *this and of rhs are determined by the exception safety guarantee of swap for lvalues of with i being index().
If an exception is thrown during the exchange of the values of *thisand rhs, the states of the values of *this and of rhsare determined by the exception safety guarantee of variant's move constructor.
The exception specification is equivalent to the logical and ofis_nothrow_move_constructible_v<> && is_nothrow_swappable_v<> for all i.