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: / [variant.ctor], constructors constexpr variant() noexcept(see below); constexpr variant(const variant&) noexcept(see below); 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&&.); / [variant.dtor], destructor constexpr ~variant(); / [variant.assign], assignment constexpr variant& operator=(const variant&); constexpr variant& operator=(variant&&) noexcept(see below); template<class T> constexpr variant& operator=(T&&) noexcept(see below); / [variant.mod], modifiers 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&&.); / [variant.status], value status constexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; / [variant.swap], swap constexpr void swap(variant&) noexcept(see below); / [variant.visit], visitation 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 variant object's contained value, is nested within ([intro.object]) the variant object.
All types in Types shall meet the Cpp17Destructible requirements (Table 35).
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.
In the descriptions that follow, let i be in the range [0, sizeof.(Types)), and
constexpr variant() noexcept(see below);
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
The exception specification is equivalent to is_nothrow_default_constructible_v<
[Note 1: 
See also class monostate.
— end note]
constexpr variant(const variant& w) noexcept(see below);
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.
Remarks: This constructor is defined as deleted unless is_copy_constructible_v<
If is_trivially_copy_constructible_v<
The exception specification is equivalent to the logical and of is_nothrow_copy_constructible_v<
constexpr variant(variant&& w) noexcept(see below);
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.
Remarks: The exception specification is equivalent to the logical and of is_nothrow_move_constructible_v<
If is_trivially_move_constructible_v<
template<class T> constexpr variant(T&& t) noexcept(see below);
Let
The overload FUN(
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<
  • 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
Remarks: The exception specification is equivalent to is_nothrow_constructible_v<
If
template<class T, class. Args> constexpr explicit variant(in_place_type_t<T>, Args&&. args);
Effects: Direct-non-list-initializes the contained value of type T with std​::​forward<Args>(args)..
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);
Effects: Direct-non-list-initializes the contained value of type T with il, std​::​forward<Args>(​args)..
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);
Effects: Direct-non-list-initializes the contained value of type
Remarks: If
template<size_t I, class U, class. Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&. args);
Effects: Direct-non-list-initializes the contained value of type
Remarks: If
constexpr ~variant();
Effects: If valueless_by_exception() is false, destroys the currently contained value.
Remarks: If is_trivially_destructible_v<
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 rhs to the value contained in *this.
  • Otherwise, if either is_nothrow_copy_constructible_v<
  • Otherwise, equivalent to operator=(variant(rhs)).
Remarks: This operator is defined as deleted unless is_copy_constructible_v<
If is_trivially_copy_constructible_v<
constexpr variant& operator=(variant&& rhs) noexcept(see below);
Constraints: is_move_constructible_v<
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<
The exception specification is equivalent to is_nothrow_move_constructible_v<
  • If an exception is thrown during the call to
  • If an exception is thrown during the call to
template<class T> constexpr variant& operator=(T&& t) noexcept(see below);
Let
The overload FUN(
Constraints:
  • is_same_v<remove_cvref_t<T>, variant> is false,
  • is_assignable_v<
  • 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
  • Otherwise, if is_nothrow_constructible_v<
  • Otherwise, equivalent to emplace<j>(
Postconditions: holds_alternative<
Remarks: The exception specification is equivalent to: is_nothrow_assignable_v<T
template<class T, class. Args> constexpr T& emplace(Args&&. args);
Constraints: is_constructible_v<T, Args..> is true, and T 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);
Effects: Destroys the currently contained value if valueless_by_exception() is false.
Then direct-non-list-initializes the contained value of type
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);
Effects: Destroys the currently contained value if valueless_by_exception() is false.
Then direct-non-list-initializes the contained value of type
Remarks: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value.
constexpr bool valueless_by_exception() const noexcept;
[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 a variant<float, int> can become valueless_by_exception(), for instance by struct 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.
constexpr void swap(variant& rhs) noexcept(see below);
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
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
If an exception is thrown during the exchange of the values of *this and rhs, the states of the values of *this and of rhs are determined by the exception safety guarantee of variant's move constructor.
The exception specification is equivalent to the logical and of is_nothrow_move_constructible_v<

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant