22 General utilities library [utilities] (original) (raw)
22.6 Variants [variant]
22.6.1 General [variant.general]
22.6.2 Header synopsis [variant.syn]
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.4 variant helper classes [variant.helper]
22.6.5 Value access [variant.get]
22.6.6 Relational operators [variant.relops]
22.6.7 Visitation [variant.visit]
22.6.8 Class monostate [variant.monostate]
22.6.9 monostate relational operators [variant.monostate.relops]
22.6.10 Specialized algorithms [variant.specalg]
22.6.11 Class bad_variant_access [variant.bad.access]
22.6.12 Hash support [variant.hash]
22.6.1 General [variant.general]
A variant object holds and manages the lifetime of a value.
If the variant holds a value, that value's type has to be one of the template argument types given to variant.
These template arguments are called alternatives.
In [variant],GET denotes a set of exposition-only function templates ([variant.get]).
22.6.2 Header synopsis [variant.syn]
#include <compare> namespace std { template<class... Types> class variant;template<class T> struct variant_size; template<class T> struct variant_size<const T>;template<class T> constexpr size_t variant_size_v = variant_size<T>::value;template<class... Types> struct variant_size<variant<Types...>>;template<size_t I, class T> struct variant_alternative; template<size_t I, class T> struct variant_alternative<I, const T>;template<size_t I, class T> using variant_alternative_t = variant_alternative<I, T>::type;template<size_t I, class... Types> struct variant_alternative<I, variant<Types...>>;inline constexpr size_t variant_npos = -1;template<class T, class... Types> constexpr bool holds_alternative(const variant<Types...>&) noexcept;template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>&); template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&); template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&); template<class T, class... Types> constexpr T& get(variant<Types...>&); template<class T, class... Types> constexpr T&& get(variant<Types...>&&); template<class T, class... Types> constexpr const T& get(const variant<Types...>&); template<class T, class... Types> constexpr const T&& get(const variant<Types...>&&); template<size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>*) noexcept;template<size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>*) noexcept;template<class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>*) noexcept;template<class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>*) noexcept;template<class... Types> constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);template<class... Types> constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);template<class... Types> constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);template<class... Types> constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);template<class... Types> constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);template<class... Types> constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);template<class... Types> requires (three_way_comparable<Types> && ...) constexpr common_comparison_category_t<compare_three_way_result_t<Types>...> operator<=>(const variant<Types...>&, const variant<Types...>&);template<class Visitor, class... Variants> constexpr see below visit(Visitor&&, Variants&&...);template<class R, class Visitor, class... Variants> constexpr R visit(Visitor&&, Variants&&...);struct monostate;constexpr bool operator==(monostate, monostate) noexcept;constexpr strong_ordering operator<=>(monostate, monostate) noexcept;template<class... Types> constexpr void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);class bad_variant_access;template<class T> struct hash;template<class... Types> struct hash<variant<Types...>>;template<> struct hash<monostate>;}
22.6.3 Class template variant [variant.variant]
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.
22.6.4 variant helper classes [variant.helper]
template<class T> struct variant_size;
All specializations of variant_size meet theCpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_constant<size_t, N> for some N.
template<class T> struct variant_size<const T>;
Let VS denote variant_size<T> of the cv-unqualified type T.
Then each specialization of the template meets theCpp17UnaryTypeTrait requirements ([meta.rqmts]) with a base characteristic of integral_constant<size_t, VS::value>.
template<class... Types> struct variant_size<variant<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class T> struct variant_alternative<I, const T>;
Let VA denote variant_alternative<I, T> of the cv-unqualified type T.
Then each specialization of the template meets the Cpp17TransformationTrait requirements ([meta.rqmts]) with a member typedef type that names the type add_const_t<VA::type>.
variant_alternative<I, variant<Types...>>::type
Mandates: I < sizeof...(Types).
22.6.5 Value access [variant.get]
template<class T, class... Types> constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
Mandates: The type T occurs exactly once in Types.
Returns: true if index() is equal to the zero-based index of T in Types.
template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& _GET_(variant<Types...>& v); // _exposition only_ template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& _GET_(variant<Types...>&& v); // _exposition only_ template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& _GET_(const variant<Types...>& v); // _exposition only_ template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& _GET_(const variant<Types...>&& v); // _exposition only_
Mandates: I < sizeof...(Types).
Preconditions: v.index() is I.
Returns: A reference to the object stored in the variant.
template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v);template<size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v);template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v);template<size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v);
Mandates: I < sizeof...(Types).
Effects: If v.index() is I, returns a reference to the object stored in the variant.
Otherwise, throws an exception of type bad_variant_access.
template<class T, class... Types> constexpr T& get(variant<Types...>& v);template<class T, class... Types> constexpr T&& get(variant<Types...>&& v);template<class T, class... Types> constexpr const T& get(const variant<Types...>& v);template<class T, class... Types> constexpr const T&& get(const variant<Types...>&& v);
Mandates: The type T occurs exactly once in Types.
Effects: If v holds a value of type T, returns a reference to that value.
Otherwise, throws an exception of type bad_variant_access.
template<size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>* v) noexcept;template<size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>* v) noexcept;
Mandates: I < sizeof...(Types).
Returns: A pointer to the value stored in the variant, if v != nullptrand v->index() == I.
Otherwise, returns nullptr.
template<class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>* v) noexcept;template<class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>* v) noexcept;
Mandates: The type T occurs exactly once in Types.
Effects: Equivalent to: return get_if<i>(v); with i being the zero-based index of T in Types.
22.6.6 Relational operators [variant.relops]
template<class... Types> constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) == GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.index() != w.index(), false; otherwise if v.valueless_by_exception(), true; otherwise GET<i>(v) == GET<i>(w) with i being v.index().
template<class... Types> constexpr bool operator!=(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) != GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.index() != w.index(), true; otherwise if v.valueless_by_exception(), false; otherwise GET<i>(v) != GET<i>(w) with i being v.index().
template<class... Types> constexpr bool operator<(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) < _GET_<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If w.valueless_by_exception(), false; otherwise if v.valueless_by_exception(), true; otherwise, if v.index() < w.index(), true; otherwise if v.index() > w.index(), false; otherwise GET<i>(v) < _GET_<i>(w) with i being v.index().
template<class... Types> constexpr bool operator>(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) > GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.valueless_by_exception(), false; otherwise if w.valueless_by_exception(), true; otherwise, if v.index() > w.index(), true; otherwise if v.index() < w.index(), false; otherwise _GET_<i>(v) > GET<i>(w) with i being v.index().
template<class... Types> constexpr bool operator<=(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) <= _GET_<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If v.valueless_by_exception(), true; otherwise if w.valueless_by_exception(), false; otherwise, if v.index() < w.index(), true; otherwise if v.index() > w.index(), false; otherwise GET<i>(v) <= _GET_<i>(w) with i being v.index().
template<class... Types> constexpr bool operator>=(const variant<Types...>& v, const variant<Types...>& w);
Constraints: GET<i>(v) >= GET<i>(w) is a valid expression that is convertible to bool, for all i.
Returns: If w.valueless_by_exception(), true; otherwise if v.valueless_by_exception(), false; otherwise, if v.index() > w.index(), true; otherwise if v.index() < w.index(), false; otherwise _GET_<i>(v) >= GET<i>(w) with i being v.index().
template<class... Types> requires ([three_way_comparable](cmp.concept#concept:three%5Fway%5Fcomparable "17.12.4 Concept three_way_comparable [cmp.concept]")<Types> && ...) constexpr common_comparison_category_t<compare_three_way_result_t<Types>...> operator<=>(const variant<Types...>& v, const variant<Types...>& w);
Effects: Equivalent to:if (v.valueless_by_exception() && w.valueless_by_exception()) return strong_ordering::equal;if (v.valueless_by_exception()) return strong_ordering::less;if (w.valueless_by_exception()) return strong_ordering::greater;if (auto c = v.index() <=> w.index(); c != 0) return c;return GET<i>(v) <=> GET<i>(w);with i being v.index().
22.6.7 Visitation [variant.visit]
template<class Visitor, class... Variants> constexpr _see below_ visit(Visitor&& vis, Variants&&... vars);template<class R, class Visitor, class... Variants> constexpr R visit(Visitor&& vis, Variants&&... vars);
Let as-variant denote the following exposition-only function templates:template<class... Ts> constexpr auto&& as-variant(variant<Ts...>& var) { return var; } template<class... Ts> constexpr auto&& as-variant(const variant<Ts...>& var) { return var; } template<class... Ts> constexpr auto&& as-variant(variant<Ts...>&& var) { return std::move(var); } template<class... Ts> constexpr auto&& as-variant(const variant<Ts...>&& var) { return std::move(var); }
Let n be sizeof...(Variants).
For each , let denote the type
decltype(as-variant(std::forward<>())).
Constraints: is a valid type for all .
Let V denote the pack of types .
Let m be a pack of n values of type size_t.
Such a pack is valid if
for all .
For each valid pack m, let e(m) denote the expression:INVOKE(std::forward<Visitor>(vis), GET<m>(std::forward<V>(vars))...) for the first form and_INVOKE_<R>(std::forward<Visitor>(vis), GET<m>(std::forward<V>(vars))...) for the second form.
Mandates: For each valid pack m, e(m) is a valid expression.
All such expressions are of the same type and value category.
Returns: e(m), where m is the pack for which is as-variant(vars).index() for all .
The return type is decltype(e(m))for the first form.
Throws: bad_variant_access if(as-variant(vars).valueless_by_exception() || ...)is true.
Complexity: For n ≤ 1, the invocation of the callable object is implemented in constant time, i.e., for , it does not depend on the number of alternative types of .
For , the invocation of the callable object has no complexity requirements.
template<class Self, class Visitor> constexpr decltype(auto) visit(this Self&& self, Visitor&& vis);
Let V be_OVERRIDE_REF_(Self&&, COPY_CONST(remove_reference_t<Self>, variant)) ([forward]).
Effects: Equivalent to: return std::visit(std::forward<Visitor>(vis), (V)self);
template<class R, class Self, class Visitor> constexpr R visit(this Self&& self, Visitor&& vis);
Let V be_OVERRIDE_REF_(Self&&, COPY_CONST(remove_reference_t<Self>, variant)) ([forward]).
Effects: Equivalent to: return std::visit<R>(std::forward<Visitor>(vis), (V)self);
22.6.8 Class monostate [variant.monostate]
The class monostate can serve as a first alternative type for a variant to make the variant type default constructible.
22.6.9 monostate relational operators [variant.monostate.relops]
constexpr bool operator==(monostate, monostate) noexcept { return true; } constexpr strong_ordering operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; }
[Note 1:
monostate objects have only a single state; they thus always compare equal.
— _end note_]
22.6.10 Specialized algorithms [variant.specalg]
template<class... Types> constexpr void swap(variant<Types...>& v, variant<Types...>& w) noexcept(_see below_);
Constraints: is_move_constructible_v<> && is_swappable_v<>is true for all i.
Effects: Equivalent to v.swap(w).
Remarks: The exception specification is equivalent to noexcept(v.swap(w)).
22.6.11 Class bad_variant_access [variant.bad.access]
namespace std { class bad_variant_access : public exception { public: constexpr const char* what() const noexcept override;};}
Objects of type bad_variant_access are thrown to report invalid accesses to the value of a variant object.
constexpr const char* what() const noexcept override;
Returns: An implementation-defined ntbs, which during constant evaluation is encoded with the ordinary literal encoding ([lex.ccon]).
22.6.12 Hash support [variant.hash]
template<class... Types> struct hash<variant<Types...>>;
The specialization hash<variant<Types...>> is enabled ([unord.hash]) if and only if every specialization in hash<remove_const_t<Types>>... is enabled.
The member functions are not guaranteed to be noexcept.
template<> struct hash<monostate>;