[variant] # 22 General utilities library [[utilities]](./#utilities) ## 22.6 Variants [variant] ### [22.6.1](#general) General [[variant.general]](variant.general) [1](#general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5532) A variant object holds and manages the lifetime of a value[.](#general-1.sentence-1) If the variant holds a value, that value's type has to be one of the template argument types given to variant[.](#general-1.sentence-2) These template arguments are called alternatives[.](#general-1.sentence-3) [2](#general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5538) In [variant],*GET* denotes a set of exposition-only function templates ([[variant.get]](#get "22.6.5 Value access"))[.](#general-2.sentence-1) ### [22.6.2](#syn) Header synopsis [[variant.syn]](variant.syn) // mostly freestanding#include // see [[compare.syn]](compare.syn "17.12.1 Header synopsis")namespace std {// [[variant.variant]](#variant "22.6.3 Class template variant"), class template varianttemplateclass variant; // [[variant.helper]](#helper "22.6.4 variant helper classes"), variant helper classestemplate struct variant_size; // *not defined*template struct variant_size; templateconstexpr size_t [variant_size_v](#lib:variant_size_v "22.6.2 Header synopsis [variant.syn]") = variant_size::value; templatestruct variant_size>; template struct variant_alternative; // *not defined*template struct variant_alternative; templateusing [variant_alternative_t](#lib:variant_alternative_t "22.6.2 Header synopsis [variant.syn]") = typename variant_alternative::type; templatestruct variant_alternative>; inline constexpr size_t variant_npos = -1; // [[variant.get]](#get "22.6.5 Value access"), value accesstemplateconstexpr bool holds_alternative(const variant&) noexcept; templateconstexpr variant_alternative_t>& get(variant&); // freestanding-deletedtemplateconstexpr variant_alternative_t>&& get(variant&&); // freestanding-deletedtemplateconstexpr const variant_alternative_t>& get(const variant&); // freestanding-deletedtemplateconstexpr const variant_alternative_t>&& get(const variant&&); // freestanding-deletedtemplateconstexpr T& get(variant&); // freestanding-deletedtemplateconstexpr T&& get(variant&&); // freestanding-deletedtemplateconstexpr const T& get(const variant&); // freestanding-deletedtemplateconstexpr const T&& get(const variant&&); // freestanding-deletedtemplateconstexpr add_pointer_t>> get_if(variant*) noexcept; templateconstexpr add_pointer_t>> get_if(const variant*) noexcept; templateconstexpr add_pointer_t get_if(variant*) noexcept; templateconstexpr add_pointer_t get_if(const variant*) noexcept; // [[variant.relops]](#relops "22.6.6 Relational operators"), relational operatorstemplateconstexpr bool operator==(const variant&, const variant&); templateconstexpr bool operator!=(const variant&, const variant&); templateconstexpr bool operator<(const variant&, const variant&); templateconstexpr bool operator>(const variant&, const variant&); templateconstexpr bool operator<=(const variant&, const variant&); templateconstexpr bool operator>=(const variant&, const variant&); template requires ([three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]") && ...)constexpr common_comparison_category_t...>operator<=>(const variant&, const variant&); // [[variant.visit]](#visit "22.6.7 Visitation"), visitationtemplateconstexpr *see below* visit(Visitor&&, Variants&&...); templateconstexpr R visit(Visitor&&, Variants&&...); // [[variant.monostate]](#monostate "22.6.8 Class monostate"), class monostatestruct monostate; // [[variant.monostate.relops]](#monostate.relops "22.6.9 monostate relational operators"), monostate relational operatorsconstexpr bool operator==(monostate, monostate) noexcept; constexpr strong_ordering operator<=>(monostate, monostate) noexcept; // [[variant.specalg]](#specalg "22.6.10 Specialized algorithms"), specialized algorithmstemplateconstexpr void swap(variant&, variant&) noexcept(*see below*); // [[variant.bad.access]](#bad.access "22.6.11 Class bad_­variant_­access"), class bad_variant_accessclass bad_variant_access; // [[variant.hash]](#hash "22.6.12 Hash support"), hash supporttemplate struct hash; template struct hash>; template<> struct hash;} ### [22.6.3](#variant) Class template variant [[variant.variant]](variant.variant) #### [22.6.3.1](#variant.general) General [[variant.variant.general]](variant.variant.general) namespace std {templateclass variant {public:// [[variant.ctor]](#ctor "22.6.3.2 Constructors"), constructorsconstexpr variant() noexcept(*see below*); constexpr variant(const variant&); constexpr variant(variant&&) noexcept(*see below*); templateconstexpr variant(T&&) noexcept(*see below*); templateconstexpr explicit variant(in_place_type_t, Args&&...); templateconstexpr explicit variant(in_place_type_t, initializer_list, Args&&...); templateconstexpr explicit variant(in_place_index_t, Args&&...); templateconstexpr explicit variant(in_place_index_t, initializer_list, Args&&...); // [[variant.dtor]](#dtor "22.6.3.3 Destructor"), destructorconstexpr ~variant(); // [[variant.assign]](#assign "22.6.3.4 Assignment"), assignmentconstexpr variant& operator=(const variant&); constexpr variant& operator=(variant&&) noexcept(*see below*); template constexpr variant& operator=(T&&) noexcept(*see below*); // [[variant.mod]](#mod "22.6.3.5 Modifiers"), modifierstemplateconstexpr T& emplace(Args&&...); templateconstexpr T& emplace(initializer_list, Args&&...); templateconstexpr variant_alternative_t>& emplace(Args&&...); templateconstexpr variant_alternative_t>& emplace(initializer_list, Args&&...); // [[variant.status]](#status "22.6.3.6 Value status"), value statusconstexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // [[variant.swap]](#swap "22.6.3.7 Swap"), swapconstexpr void swap(variant&) noexcept(*see below*); // [[variant.visit]](#visit "22.6.7 Visitation"), visitationtemplateconstexpr decltype(auto) visit(this Self&&, Visitor&&); templateconstexpr R visit(this Self&&, Visitor&&); };} [1](#variant.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5722) Any instance of variant at any given time either holds a value of one of its alternative types or holds no value[.](#variant.general-1.sentence-1) 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*](#def:contained_value,variant "22.6.3.1 General [variant.variant.general]"), is nested within ([[intro.object]](intro.object "6.8.2 Object model")) thevariant object[.](#variant.general-1.sentence-2) [2](#variant.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5731) All types in Types shall meet the [*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements (Table [35](utility.arg.requirements#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements"))[.](#variant.general-2.sentence-1) [3](#variant.general-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5735) A program that instantiates the definition of variant with no template arguments is ill-formed[.](#variant.general-3.sentence-1) [4](#variant.general-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5739) If a program declares an explicit or partial specialization of variant, the program is ill-formed, no diagnostic required[.](#variant.general-4.sentence-1) #### [22.6.3.2](#ctor) Constructors [[variant.ctor]](variant.ctor) [1](#ctor-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5745) In the descriptions that follow, let i be in the range [0, sizeof...(Types)), and Ti be the ith type in Types[.](#ctor-1.sentence-1) [🔗](#lib:variant,constructor) `constexpr variant() noexcept(see below); ` [2](#ctor-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5755) *Constraints*: is_default_constructible_v is true[.](#ctor-2.sentence-1) [3](#ctor-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5759) *Effects*: Constructs a variant holding a value-initialized value of type T0[.](#ctor-3.sentence-1) [4](#ctor-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5763) *Postconditions*: valueless_by_exception() is false and index() is 0[.](#ctor-4.sentence-1) [5](#ctor-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5767) *Throws*: Any exception thrown by the value-initialization of T0[.](#ctor-5.sentence-1) [6](#ctor-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5771) *Remarks*: This function is constexpr if and only if the value-initialization of the alternative type T0 would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"))[.](#ctor-6.sentence-1) The exception specification is equivalent tois_nothrow_default_constructible_v[.](#ctor-6.sentence-2) [*Note [1](#ctor-note-1)*: See also class monostate[.](#ctor-6.sentence-3) — *end note*] [🔗](#lib:variant,constructor_) `constexpr variant(const variant& w); ` [7](#ctor-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5789) *Effects*: If w holds a value, initializes the variant to hold the same alternative as w and direct-initializes the contained value with *GET*(w), where j is w.index()[.](#ctor-7.sentence-1) Otherwise, initializes the variant to not hold a value[.](#ctor-7.sentence-2) [8](#ctor-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5796) *Throws*: Any exception thrown by direct-initializing any Ti for all i[.](#ctor-8.sentence-1) [9](#ctor-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5800) *Remarks*: This constructor is defined as deleted unlessis_copy_constructible_v is true for all i[.](#ctor-9.sentence-1) If is_trivially_copy_constructible_v is true for all i, this constructor is trivial[.](#ctor-9.sentence-2) [🔗](#lib:variant,constructor__) `constexpr variant(variant&& w) noexcept(see below); ` [10](#ctor-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5814) *Constraints*: is_move_constructible_v is true for all i[.](#ctor-10.sentence-1) [11](#ctor-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5818) *Effects*: If w holds a value, initializes the variant to hold the same alternative as w and direct-initializes the contained value with*GET*(std​::​move(w)), where j is w.index()[.](#ctor-11.sentence-1) Otherwise, initializes the variant to not hold a value[.](#ctor-11.sentence-2) [12](#ctor-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5825) *Throws*: Any exception thrown by move-constructing any Ti for all i[.](#ctor-12.sentence-1) [13](#ctor-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5829) *Remarks*: The exception specification is equivalent to the logical and ofis_nothrow_move_constructible_v for all i[.](#ctor-13.sentence-1) If is_trivially_move_constructible_v is true for all i, this constructor is trivial[.](#ctor-13.sentence-2) [🔗](#lib:variant,constructor___) `template constexpr variant(T&& t) noexcept(see below); ` [14](#ctor-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5843) Let Tj be a type that is determined as follows: build an imaginary function *FUN*(Ti) for each alternative type Ti for which Ti x[] = {std​::​forward(t)}; is well-formed for some invented variable x[.](#ctor-14.sentence-1) The overload *FUN*(Tj) selected by overload resolution for the expression *FUN*(std​::​forward(​t)) defines the alternative Tj which is the type of the contained value after construction[.](#ctor-14.sentence-2) [15](#ctor-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5854) *Constraints*: - [(15.1)](#ctor-15.1) sizeof...(Types) is nonzero, - [(15.2)](#ctor-15.2) is_same_v, variant> is false, - [(15.3)](#ctor-15.3) remove_cvref_t is neither a specialization of in_place_type_t nor a specialization of in_place_index_t, - [(15.4)](#ctor-15.4) is_constructible_v is true, and - [(15.5)](#ctor-15.5) the expression *FUN*(​std​::​forward(t)) (with *FUN* being the above-mentioned set of imaginary functions) is well-formed[.](#ctor-15.sentence-1) [*Note [2](#ctor-note-2)*: variant v("abc"); is ill-formed, as both alternative types have an equally viable constructor for the argument[.](#ctor-15.5.sentence-2) — *end note*] [16](#ctor-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5884) *Effects*: Initializes *this to hold the alternative type Tj and direct-non-list-initializes the contained value with std​::​forward(t)[.](#ctor-16.sentence-1) [17](#ctor-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5889) *Postconditions*: holds_alternative(*this) is true[.](#ctor-17.sentence-1) [18](#ctor-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5893) *Throws*: Any exception thrown by the initialization of the selected alternative Tj[.](#ctor-18.sentence-1) [19](#ctor-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5897) *Remarks*: The exception specification is equivalent tois_nothrow_constructible_v[.](#ctor-19.sentence-1) If Tj's selected constructor is a constexpr constructor, this constructor is a constexpr constructor[.](#ctor-19.sentence-2) [🔗](#lib:variant,constructor____) `template constexpr explicit variant(in_place_type_t, Args&&... args); ` [20](#ctor-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5911) *Constraints*: - [(20.1)](#ctor-20.1) There is exactly one occurrence of T in Types... and - [(20.2)](#ctor-20.2) is_constructible_v is true[.](#ctor-20.sentence-1) [21](#ctor-21) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5918) *Effects*: Direct-non-list-initializes the contained value of type T with std​::​forward(args)...[.](#ctor-21.sentence-1) [22](#ctor-22) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5923) *Postconditions*: holds_alternative(*this) is true[.](#ctor-22.sentence-1) [23](#ctor-23) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5927) *Throws*: Any exception thrown by calling the selected constructor of T[.](#ctor-23.sentence-1) [24](#ctor-24) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5931) *Remarks*: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor[.](#ctor-24.sentence-1) [🔗](#lib:variant,constructor_____) `template constexpr explicit variant(in_place_type_t, initializer_list il, Args&&... args); ` [25](#ctor-25) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5944) *Constraints*: - [(25.1)](#ctor-25.1) There is exactly one occurrence of T in Types... and - [(25.2)](#ctor-25.2) is_constructible_v&, Args...> is true[.](#ctor-25.sentence-1) [26](#ctor-26) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5951) *Effects*: Direct-non-list-initializes the contained value of type T with il, std​::​forward(​args)...[.](#ctor-26.sentence-1) [27](#ctor-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5956) *Postconditions*: holds_alternative(*this) is true[.](#ctor-27.sentence-1) [28](#ctor-28) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5960) *Throws*: Any exception thrown by calling the selected constructor of T[.](#ctor-28.sentence-1) [29](#ctor-29) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5964) *Remarks*: If T's selected constructor is a constexpr constructor, this constructor is a constexpr constructor[.](#ctor-29.sentence-1) [🔗](#lib:variant,constructor______) `template constexpr explicit variant(in_place_index_t, Args&&... args); ` [30](#ctor-30) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5976) *Constraints*: - [(30.1)](#ctor-30.1) I is less than sizeof...(Types) and - [(30.2)](#ctor-30.2) is_constructible_v is true[.](#ctor-30.sentence-1) [31](#ctor-31) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5985) *Effects*: Direct-non-list-initializes the contained value of type TI with std​::​forward(args)...[.](#ctor-31.sentence-1) [32](#ctor-32) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5990) *Postconditions*: index() is I[.](#ctor-32.sentence-1) [33](#ctor-33) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5994) *Throws*: Any exception thrown by calling the selected constructor of TI[.](#ctor-33.sentence-1) [34](#ctor-34) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5998) *Remarks*: If TI's selected constructor is a constexpr constructor, this constructor is a constexpr constructor[.](#ctor-34.sentence-1) [🔗](#lib:variant,constructor_______) `template constexpr explicit variant(in_place_index_t, initializer_list il, Args&&... args); ` [35](#ctor-35) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6011) *Constraints*: - [(35.1)](#ctor-35.1) I is less than sizeof...(Types) and - [(35.2)](#ctor-35.2) is_constructible_v&, Args...> is true[.](#ctor-35.sentence-1) [36](#ctor-36) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6020) *Effects*: Direct-non-list-initializes the contained value of type TI with il, std​::​forward(​args)...[.](#ctor-36.sentence-1) [37](#ctor-37) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6025) *Postconditions*: index() is I[.](#ctor-37.sentence-1) [38](#ctor-38) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6029) *Remarks*: If TI's selected constructor is a constexpr constructor, this constructor is a constexpr constructor[.](#ctor-38.sentence-1) #### [22.6.3.3](#dtor) Destructor [[variant.dtor]](variant.dtor) [🔗](#lib:variant,destructor) `constexpr ~variant(); ` [1](#dtor-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6043) *Effects*: If valueless_by_exception() is false, destroys the currently contained value[.](#dtor-1.sentence-1) [2](#dtor-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6048) *Remarks*: If is_trivially_destructible_v is true for all Ti, then this destructor is trivial[.](#dtor-2.sentence-1) #### [22.6.3.4](#assign) Assignment [[variant.assign]](variant.assign) [🔗](#lib:operator=,variant) `constexpr variant& operator=(const variant& rhs); ` [1](#assign-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6062) Let j be rhs.index()[.](#assign-1.sentence-1) [2](#assign-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6065) *Effects*: - [(2.1)](#assign-2.1) If neither *this nor rhs holds a value, there is no effect[.](#assign-2.1.sentence-1) - [(2.2)](#assign-2.2) Otherwise, if *this holds a value but rhs does not, destroys the value contained in *this and sets *this to not hold a value[.](#assign-2.2.sentence-1) - [(2.3)](#assign-2.3) Otherwise, if index() == j, assigns the value contained in rhs to the value contained in *this[.](#assign-2.3.sentence-1) - [(2.4)](#assign-2.4) Otherwise, if either is_nothrow_copy_constructible_v is true oris_nothrow_move_constructible_v is false, equivalent to emplace(*GET*(rhs))[.](#assign-2.4.sentence-1) - [(2.5)](#assign-2.5) Otherwise, equivalent to operator=(variant(rhs))[.](#assign-2.5.sentence-1) [3](#assign-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6085) *Postconditions*: index() == rhs.index()[.](#assign-3.sentence-1) [4](#assign-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6089) *Returns*: *this[.](#assign-4.sentence-1) [5](#assign-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6093) *Remarks*: This operator is defined as deleted unlessis_copy_constructible_v &&is_copy_assignable_v is true for all i[.](#assign-5.sentence-1) 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[.](#assign-5.sentence-2) [🔗](#lib:operator=,variant_) `constexpr variant& operator=(variant&& rhs) noexcept(see below); ` [6](#assign-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6111) Let j be rhs.index()[.](#assign-6.sentence-1) [7](#assign-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6114) *Constraints*: is_move_constructible_v &&is_move_assignable_v istrue for all i[.](#assign-7.sentence-1) [8](#assign-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6120) *Effects*: - [(8.1)](#assign-8.1) If neither *this nor rhs holds a value, there is no effect[.](#assign-8.1.sentence-1) - [(8.2)](#assign-8.2) Otherwise, if *this holds a value but rhs does not, destroys the value contained in *this and sets *this to not hold a value[.](#assign-8.2.sentence-1) - [(8.3)](#assign-8.3) Otherwise, if index() == j, assigns *GET*(std​::​move(rhs)) to the value contained in *this[.](#assign-8.3.sentence-1) - [(8.4)](#assign-8.4) Otherwise, equivalent to emplace(*GET*(std​::​move(rhs)))[.](#assign-8.4.sentence-1) [9](#assign-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6135) *Returns*: *this[.](#assign-9.sentence-1) [10](#assign-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6139) *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[.](#assign-10.sentence-1) The exception specification is equivalent tois_nothrow_move_constructible_v && is_nothrow_move_assignable_v for all i[.](#assign-10.sentence-2) - [(10.1)](#assign-10.1) If an exception is thrown during the call to Tj's move construction (with j being rhs.index()), the variant will hold no value[.](#assign-10.1.sentence-1) - [(10.2)](#assign-10.2) If an exception is thrown during the call to Tj's move assignment, the state of the contained value is as defined by the exception safety guarantee of Tj's move assignment; index() will be j[.](#assign-10.2.sentence-1) [🔗](#lib:operator=,variant__) `template constexpr variant& operator=(T&& t) noexcept(see below); ` [11](#assign-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6162) Let Tj be a type that is determined as follows: build an imaginary function *FUN*(Ti) for each alternative type Ti for which Ti x[] = {std​::​forward(t)}; is well-formed for some invented variable x[.](#assign-11.sentence-1) The overload *FUN*(Tj) selected by overload resolution for the expression *FUN*(std​::​forward(​t)) defines the alternative Tj which is the type of the contained value after assignment[.](#assign-11.sentence-2) [12](#assign-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6173) *Constraints*: - [(12.1)](#assign-12.1) is_same_v, variant> is false, - [(12.2)](#assign-12.2) is_assignable_v && is_constructible_v is true, and - [(12.3)](#assign-12.3) the expression *FUN*(std​::​forward(t)) (with *FUN* being the above-mentioned set of imaginary functions) is well-formed[.](#assign-12.sentence-1) [*Note [1](#assign-note-1)*: variant v; v = "abc"; is ill-formed, as both alternative types have an equally viable constructor for the argument[.](#assign-12.3.sentence-2) — *end note*] [13](#assign-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6197) *Effects*: - [(13.1)](#assign-13.1) If *this holds a Tj, assigns std​::​forward(t) to the value contained in *this[.](#assign-13.1.sentence-1) - [(13.2)](#assign-13.2) Otherwise, if is_nothrow_constructible_v ||!is_nothrow_move_constructible_v is true, equivalent to emplace(std​::​forward(t))[.](#assign-13.2.sentence-1) - [(13.3)](#assign-13.3) Otherwise, equivalent to emplace(Tj(std​::​forward(t)))[.](#assign-13.3.sentence-1) [14](#assign-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6211) *Postconditions*: holds_alternative(*this) is true, with Tj selected by the imaginary function overload resolution described above[.](#assign-14.sentence-1) [15](#assign-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6216) *Returns*: *this[.](#assign-15.sentence-1) [16](#assign-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6220) *Remarks*: The exception specification is equivalent to:is_nothrow_assignable_v && is_nothrow_constructible_v - [(16.1)](#assign-16.1) If an exception is thrown during the assignment of std​::​forward(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[.](#assign-16.1.sentence-1) - [(16.2)](#assign-16.2) If an exception is thrown during the initialization of the contained value, the variant object is permitted to not hold a value[.](#assign-16.2.sentence-1) #### [22.6.3.5](#mod) Modifiers [[variant.mod]](variant.mod) [🔗](#lib:emplace,variant) `template constexpr T& emplace(Args&&... args); ` [1](#mod-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6244) *Constraints*: is_constructible_v is true, andT occurs exactly once in Types[.](#mod-1.sentence-1) [2](#mod-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6249) *Effects*: Equivalent to:return emplace(std::forward(args)...); where I is the zero-based index of T in Types[.](#mod-2.sentence-1) [🔗](#lib:emplace,variant_) `template constexpr T& emplace(initializer_list il, Args&&... args); ` [3](#mod-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6265) *Constraints*: is_constructible_v&, Args...> is true, and T occurs exactly once in Types[.](#mod-3.sentence-1) [4](#mod-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6270) *Effects*: Equivalent to:return emplace(il, std::forward(args)...); where I is the zero-based index of T in Types[.](#mod-4.sentence-1) [🔗](#lib:emplace,variant__) `template constexpr variant_alternative_t>& emplace(Args&&... args); ` [5](#mod-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6286) *Mandates*: I < sizeof...(Types)[.](#mod-5.sentence-1) [6](#mod-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6290) *Constraints*: is_constructible_v is true[.](#mod-6.sentence-1) [7](#mod-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6294) *Effects*: Destroys the currently contained value if valueless_by_exception() is false[.](#mod-7.sentence-1) Then direct-non-list-initializes the contained value of type TI with the arguments std​::​forward(args)...[.](#mod-7.sentence-2) [8](#mod-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6301) *Postconditions*: index() is I[.](#mod-8.sentence-1) [9](#mod-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6305) *Returns*: A reference to the new contained value[.](#mod-9.sentence-1) [10](#mod-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6309) *Throws*: Any exception thrown during the initialization of the contained value[.](#mod-10.sentence-1) [11](#mod-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6313) *Remarks*: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value[.](#mod-11.sentence-1) [🔗](#lib:emplace,variant___) `template constexpr variant_alternative_t>& emplace(initializer_list il, Args&&... args); ` [12](#mod-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6327) *Mandates*: I < sizeof...(Types)[.](#mod-12.sentence-1) [13](#mod-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6331) *Constraints*: is_constructible_v&, Args...> is true[.](#mod-13.sentence-1) [14](#mod-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6335) *Effects*: Destroys the currently contained value if valueless_by_exception() is false[.](#mod-14.sentence-1) Then direct-non-list-initializes the contained value of type TI with il, std​::​forward(args)...[.](#mod-14.sentence-2) [15](#mod-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6342) *Postconditions*: index() is I[.](#mod-15.sentence-1) [16](#mod-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6346) *Returns*: A reference to the new contained value[.](#mod-16.sentence-1) [17](#mod-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6350) *Throws*: Any exception thrown during the initialization of the contained value[.](#mod-17.sentence-1) [18](#mod-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6354) *Remarks*: If an exception is thrown during the initialization of the contained value, the variant is permitted to not hold a value[.](#mod-18.sentence-1) #### [22.6.3.6](#status) Value status [[variant.status]](variant.status) [🔗](#lib:valueless_by_exception,variant) `constexpr bool valueless_by_exception() const noexcept; ` [1](#status-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6368) *Effects*: Returns false if and only if the variant holds a value[.](#status-1.sentence-1) [2](#status-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6372) [*Note [1](#status-note-1)*: It is possible for a variant to hold no value if an exception is thrown during a type-changing assignment or emplacement[.](#status-2.sentence-1) The latter means that even avariant can become valueless_by_exception(), for instance bystruct S { operator int() { throw 42; }}; variant v{12.f}; v.emplace<1>(S()); — *end note*] [🔗](#lib:index,variant) `constexpr size_t index() const noexcept; ` [3](#status-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6393) *Effects*: If valueless_by_exception() is true, returns variant_npos[.](#status-3.sentence-1) Otherwise, returns the zero-based index of the alternative of the contained value[.](#status-3.sentence-2) #### [22.6.3.7](#swap) Swap [[variant.swap]](variant.swap) [🔗](#lib:swap,variant) `constexpr void swap(variant& rhs) noexcept(see below); ` [1](#swap-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6407) *Mandates*: is_move_constructible_v is true for all i[.](#swap-1.sentence-1) [2](#swap-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6411) *Preconditions*: Each Ti meets the [*Cpp17Swappable*](swappable.requirements#:Cpp17Swappable "16.4.4.3 Swappable requirements [swappable.requirements]") requirements ([[swappable.requirements]](swappable.requirements "16.4.4.3 Swappable requirements"))[.](#swap-2.sentence-1) [3](#swap-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6415) *Effects*: - [(3.1)](#swap-3.1) If valueless_by_exception() && rhs.valueless_by_exception() no effect[.](#swap-3.1.sentence-1) - [(3.2)](#swap-3.2) Otherwise, if index() == rhs.index(), calls swap(*GET*(*this), *GET*(rhs)) where i is index()[.](#swap-3.2.sentence-1) - [(3.3)](#swap-3.3) Otherwise, exchanges values of rhs and *this[.](#swap-3.3.sentence-1) [4](#swap-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6426) *Throws*: If index() == rhs.index(), any exception thrown by swap(*GET*(*this), *GET*(rhs)) with i being index()[.](#swap-4.sentence-1) Otherwise, any exception thrown by the move constructor of Ti or Tj with i being index() and j being rhs.index()[.](#swap-4.sentence-2) [5](#swap-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6435) *Remarks*: If an exception is thrown during the call to function swap(*GET*(*this), *GET*(rhs)), the states of the contained values of *this and of rhs are determined by the exception safety guarantee of swap for lvalues ofTi with i being index()[.](#swap-5.sentence-1) 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[.](#swap-5.sentence-2) The exception specification is equivalent to the logical and ofis_nothrow_move_constructible_v && is_nothrow_swappable_v for all i[.](#swap-5.sentence-3) ### [22.6.4](#helper) variant helper classes [[variant.helper]](variant.helper) [🔗](#lib:variant_size) `template struct variant_size; ` [1](#helper-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6456) All specializations of variant_size meet the[*Cpp17UnaryTypeTrait*](meta.rqmts#:Cpp17UnaryTypeTrait "21.3.2 Requirements [meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements")) with a base characteristic of integral_constant for some N[.](#helper-1.sentence-1) [🔗](#lib:variant_size_) `template struct variant_size; ` [2](#helper-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6468) Let VS denote variant_size of the cv-unqualified type T[.](#helper-2.sentence-1) Then each specialization of the template meets the[*Cpp17UnaryTypeTrait*](meta.rqmts#:Cpp17UnaryTypeTrait "21.3.2 Requirements [meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements")) with a base characteristic of integral_constant[.](#helper-2.sentence-2) [🔗](#lib:variant_size__) `template struct variant_size> : integral_constant { }; ` [🔗](#lib:variant_alternative) `template struct variant_alternative; ` [3](#helper-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6488) Let VA denote variant_alternative of the cv-unqualified type T[.](#helper-3.sentence-1) Then each specialization of the template meets the [*Cpp17TransformationTrait*](meta.rqmts#:Cpp17TransformationTrait "21.3.2 Requirements [meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements")) with a member typedef type that names the type add_const_t[.](#helper-3.sentence-2) [🔗](#lib:variant_alternative_) `variant_alternative>::type ` [4](#helper-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6501) *Mandates*: I < sizeof...(Types)[.](#helper-4.sentence-1) [5](#helper-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6505) *Type*: The type TI[.](#helper-5.sentence-1) ### [22.6.5](#get) Value access [[variant.get]](variant.get) [🔗](#lib:holds_alternative) `template constexpr bool holds_alternative(const variant& v) noexcept; ` [1](#get-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6520) *Mandates*: The type T occurs exactly once in Types[.](#get-1.sentence-1) [2](#get-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6524) *Returns*: true if index() is equal to the zero-based index of T in Types[.](#get-2.sentence-1) [🔗](#get-itemdecl:2) `template constexpr variant_alternative_t>& GET(variant& v); // exposition only template constexpr variant_alternative_t>&& GET(variant&& v); // exposition only template constexpr const variant_alternative_t>& GET(const variant& v); // exposition only template constexpr const variant_alternative_t>&& GET(const variant&& v); // exposition only ` [3](#get-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6545) *Mandates*: I < sizeof...(Types)[.](#get-3.sentence-1) [4](#get-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6549) *Preconditions*: v.index() is I[.](#get-4.sentence-1) [5](#get-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6553) *Returns*: A reference to the object stored in the variant[.](#get-5.sentence-1) [🔗](#lib:get,variant) `template constexpr variant_alternative_t>& get(variant& v); template constexpr variant_alternative_t>&& get(variant&& v); template constexpr const variant_alternative_t>& get(const variant& v); template constexpr const variant_alternative_t>&& get(const variant&& v); ` [6](#get-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6571) *Mandates*: I < sizeof...(Types)[.](#get-6.sentence-1) [7](#get-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6575) *Effects*: If v.index() is I, returns a reference to the object stored in the variant[.](#get-7.sentence-1) Otherwise, throws an exception of type bad_variant_access[.](#get-7.sentence-2) [🔗](#lib:get,variant_) `template constexpr T& get(variant& v); template constexpr T&& get(variant&& v); template constexpr const T& get(const variant& v); template constexpr const T&& get(const variant&& v); ` [8](#get-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6590) *Mandates*: The type T occurs exactly once in Types[.](#get-8.sentence-1) [9](#get-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6594) *Effects*: If v holds a value of type T, returns a reference to that value[.](#get-9.sentence-1) Otherwise, throws an exception of type bad_variant_access[.](#get-9.sentence-2) [🔗](#lib:get_if) `template constexpr add_pointer_t>> get_if(variant* v) noexcept; template constexpr add_pointer_t>> get_if(const variant* v) noexcept; ` [10](#get-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6612) *Mandates*: I < sizeof...(Types)[.](#get-10.sentence-1) [11](#get-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6616) *Returns*: A pointer to the value stored in the variant, if v != nullptr and v->index() == I[.](#get-11.sentence-1) Otherwise, returns nullptr[.](#get-11.sentence-2) [🔗](#lib:get_if_) `template constexpr add_pointer_t get_if(variant* v) noexcept; template constexpr add_pointer_t get_if(const variant* v) noexcept; ` [12](#get-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6634) *Mandates*: The type T occurs exactly once in Types[.](#get-12.sentence-1) [13](#get-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6638) *Effects*: Equivalent to: return get_if(v); with i being the zero-based index of T in Types[.](#get-13.sentence-1) ### [22.6.6](#relops) Relational operators [[variant.relops]](variant.relops) [🔗](#lib:operator==,variant) `template constexpr bool operator==(const variant& v, const variant& w); ` [1](#relops-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6653) *Constraints*: *GET*(v) == *GET*(w) is a valid expression that is convertible to bool, for all i[.](#relops-1.sentence-1) [2](#relops-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6658) *Returns*: If v.index() != w.index(), false; otherwise if v.valueless_by_exception(), true; otherwise *GET*(v) == *GET*(w) with i being v.index()[.](#relops-2.sentence-1) [🔗](#lib:operator!=,variant) `template constexpr bool operator!=(const variant& v, const variant& w); ` [3](#relops-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6672) *Constraints*: *GET*(v) != *GET*(w) is a valid expression that is convertible to bool, for all i[.](#relops-3.sentence-1) [4](#relops-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6677) *Returns*: If v.index() != w.index(), true; otherwise if v.valueless_by_exception(), false; otherwise *GET*(v) != *GET*(w) with i being v.index()[.](#relops-4.sentence-1) [🔗](#lib:operator%3c,variant) `template constexpr bool operator<(const variant& v, const variant& w); ` [5](#relops-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6691) *Constraints*: *GET*(v) < *GET*(w) is a valid expression that is convertible to bool, for all i[.](#relops-5.sentence-1) [6](#relops-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6696) *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*(v) < *GET*(w) with i being v.index()[.](#relops-6.sentence-1) [🔗](#lib:operator%3e,variant) `template constexpr bool operator>(const variant& v, const variant& w); ` [7](#relops-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6712) *Constraints*: *GET*(v) > *GET*(w) is a valid expression that is convertible to bool, for all i[.](#relops-7.sentence-1) [8](#relops-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6717) *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*(v) > *GET*(w) with i being v.index()[.](#relops-8.sentence-1) [🔗](#lib:operator%3c=,variant) `template constexpr bool operator<=(const variant& v, const variant& w); ` [9](#relops-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6733) *Constraints*: *GET*(v) <= *GET*(w) is a valid expression that is convertible to bool, for all i[.](#relops-9.sentence-1) [10](#relops-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6738) *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*(v) <= *GET*(w) with i being v.index()[.](#relops-10.sentence-1) [🔗](#lib:operator%3e=,variant) `template constexpr bool operator>=(const variant& v, const variant& w); ` [11](#relops-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6754) *Constraints*: *GET*(v) >= *GET*(w) is a valid expression that is convertible to bool, for all i[.](#relops-11.sentence-1) [12](#relops-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6759) *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*(v) >= *GET*(w) with i being v.index()[.](#relops-12.sentence-1) [🔗](#lib:operator%3c=%3e,variant) `template requires ([three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]") && ...) constexpr common_comparison_category_t...> operator<=>(const variant& v, const variant& w); ` [13](#relops-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6776) *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*(v) <=> *GET*(w); with i being v.index()[.](#relops-13.sentence-1) ### [22.6.7](#visit) Visitation [[variant.visit]](variant.visit) [🔗](#lib:visit) `template constexpr see below visit(Visitor&& vis, Variants&&... vars); template constexpr R visit(Visitor&& vis, Variants&&... vars); ` [1](#visit-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6802) Let *as-variant* denote the following exposition-only function templates:templateconstexpr auto&& *as-variant*(variant& var) { return var; }templateconstexpr auto&& *as-variant*(const variant& var) { return var; }templateconstexpr auto&& *as-variant*(variant&& var) { return std::move(var); }templateconstexpr auto&& *as-variant*(const variant&& var) { return std::move(var); } Let n be sizeof...(Variants)[.](#visit-1.sentence-2) For each 0≤i(varsi)))[.](#visit-1.sentence-3) [2](#visit-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6819) *Constraints*: Vi is a valid type for all 0≤i> for all 0≤i(vis), *GET*(std::forward(vars))...) // see [[func.require]](func.require "22.10.4 Requirements") for the first form and*INVOKE*(std::forward(vis), *GET*(std::forward(vars))...) // see [[func.require]](func.require "22.10.4 Requirements") for the second form[.](#visit-4.sentence-3) [5](#visit-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6841) *Mandates*: For each valid pack m, e(m) is a valid expression[.](#visit-5.sentence-1) All such expressions are of the same type and value category[.](#visit-5.sentence-2) [6](#visit-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6846) *Returns*: e(m), where m is the pack for whichmi is *as-variant*(varsi).index() for all 0≤i1, the invocation of the callable object has no complexity requirements[.](#visit-8.sentence-2) [🔗](#lib:visit,variant_) `template constexpr decltype(auto) visit(this Self&& self, Visitor&& vis); ` [9](#visit-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6875) Let V be*OVERRIDE_REF*(Self&&, *COPY_CONST*(remove_reference_t, variant)) ([[forward]](forward "22.2.4 Forward/move helpers"))[.](#visit-9.sentence-1) [10](#visit-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6879) *Constraints*: The call to visit does not use an explicit [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]") that begins with a type [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")[.](#visit-10.sentence-1) [11](#visit-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6885) *Effects*: Equivalent to: return std​::​visit(std​::​forward(vis), (V)self); [🔗](#lib:visit,variant__) `template constexpr R visit(this Self&& self, Visitor&& vis); ` [12](#visit-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6897) Let V be*OVERRIDE_REF*(Self&&, *COPY_CONST*(remove_reference_t, variant)) ([[forward]](forward "22.2.4 Forward/move helpers"))[.](#visit-12.sentence-1) [13](#visit-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6901) *Effects*: Equivalent to: return std​::​visit(std​::​forward(vis), (V)self); ### [22.6.8](#monostate) Class monostate [[variant.monostate]](variant.monostate) [🔗](#lib:monostate_) `struct monostate{}; ` [1](#monostate-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6915) The class monostate can serve as a first alternative type for a variant to make the variant type default constructible[.](#monostate-1.sentence-1) ### [22.6.9](#monostate.relops) monostate relational operators [[variant.monostate.relops]](variant.monostate.relops) [🔗](#lib:operator==,monostate) `constexpr bool operator==(monostate, monostate) noexcept { return true; } constexpr strong_ordering operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; } ` [1](#monostate.relops-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6932) [*Note [1](#monostate.relops-note-1)*: monostate objects have only a single state; they thus always compare equal[.](#monostate.relops-1.sentence-1) — *end note*] ### [22.6.10](#specalg) Specialized algorithms [[variant.specalg]](variant.specalg) [🔗](#lib:swap,variant_) `template constexpr void swap(variant& v, variant& w) noexcept(see below); ` [1](#specalg-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6947) *Constraints*: is_move_constructible_v && is_swappable_v is true for all i[.](#specalg-1.sentence-1) [2](#specalg-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6952) *Effects*: Equivalent to v.swap(w)[.](#specalg-2.sentence-1) [3](#specalg-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6956) *Remarks*: The exception specification is equivalent to noexcept(v.swap(w))[.](#specalg-3.sentence-1) ### [22.6.11](#bad.access) Class bad_variant_access [[variant.bad.access]](variant.bad.access) namespace std {class bad_variant_access : public exception {public:// see [[exception]](exception "17.9.3 Class exception") for the specification of the special member functionsconstexpr const char* what() const noexcept override; };} [1](#bad.access-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6974) Objects of type bad_variant_access are thrown to report invalid accesses to the value of a variant object[.](#bad.access-1.sentence-1) [🔗](#lib:what,bad_variant_access) `constexpr const char* what() const noexcept override; ` [2](#bad.access-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6984) *Returns*: An implementation-defined ntbs, which during constant evaluation is encoded with the ordinary literal encoding ([[lex.ccon]](lex.ccon "5.13.3 Character literals"))[.](#bad.access-2.sentence-1) ### [22.6.12](#hash) Hash support [[variant.hash]](variant.hash) [🔗](#lib:hash,variant) `template struct hash>; ` [1](#hash-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6999) The specialization hash> is enabled ([[unord.hash]](unord.hash "22.10.19 Class template hash")) if and only if every specialization in hash>... is enabled[.](#hash-1.sentence-1) The member functions are not guaranteed to be noexcept[.](#hash-1.sentence-2) [🔗](#lib:hash,monostate) `template<> struct hash; ` [2](#hash-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L7011) The specialization is enabled ([[unord.hash]](unord.hash "22.10.19 Class template hash"))[.](#hash-2.sentence-1)