[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:

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:

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:

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:

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:

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:

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:

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.

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:

Effects:

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>

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:

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.