Files
cppdraft_translate/cppdraft/variant.md
2025-10-25 03:02:53 +03:00

1512 lines
60 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.5Value access"))[.](#general-2.sentence-1)
### [22.6.2](#syn) Header <variant> synopsis [[variant.syn]](variant.syn)
// mostly freestanding#include <compare> // see [[compare.syn]](compare.syn "17.12.1Header <compare> synopsis")namespace std {// [[variant.variant]](#variant "22.6.3Class template variant"), class template varianttemplate<class... Types>class variant; // [[variant.helper]](#helper "22.6.4variant helper classes"), variant helper classestemplate<class T> struct variant_size; // *not defined*template<class T> struct variant_size<const T>; template<class T>constexpr size_t [variant_size_v](#lib:variant_size_v "22.6.2Header <variant> synopsis[variant.syn]") = variant_size<T>::value; template<class... Types>struct variant_size<variant<Types...>>; template<size_t I, class T> struct variant_alternative; // *not defined*template<size_t I, class T> struct variant_alternative<I, const T>; template<size_t I, class T>using [variant_alternative_t](#lib:variant_alternative_t "22.6.2Header <variant> synopsis[variant.syn]") = typename variant_alternative<I, T>::type; template<size_t I, class... Types>struct variant_alternative<I, variant<Types...>>; inline constexpr size_t variant_npos = -1; // [[variant.get]](#get "22.6.5Value access"), value accesstemplate<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...>&); // freestanding-deletedtemplate<size_t I, class... Types>constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&); // freestanding-deletedtemplate<size_t I, class... Types>constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&); // freestanding-deletedtemplate<size_t I, class... Types>constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&); // freestanding-deletedtemplate<class T, class... Types>constexpr T& get(variant<Types...>&); // freestanding-deletedtemplate<class T, class... Types>constexpr T&& get(variant<Types...>&&); // freestanding-deletedtemplate<class T, class... Types>constexpr const T& get(const variant<Types...>&); // freestanding-deletedtemplate<class T, class... Types>constexpr const T&& get(const variant<Types...>&&); // freestanding-deletedtemplate<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; // [[variant.relops]](#relops "22.6.6Relational operators"), relational operatorstemplate<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](cmp.concept#concept:three_way_comparable "17.12.4Concept three_­way_­comparable[cmp.concept]")<Types> && ...)constexpr common_comparison_category_t<compare_three_way_result_t<Types>...>operator<=>(const variant<Types...>&, const variant<Types...>&); // [[variant.visit]](#visit "22.6.7Visitation"), visitationtemplate<class Visitor, class... Variants>constexpr *see below* visit(Visitor&&, Variants&&...); template<class R, class Visitor, class... Variants>constexpr R visit(Visitor&&, Variants&&...); // [[variant.monostate]](#monostate "22.6.8Class monostate"), class monostatestruct monostate; // [[variant.monostate.relops]](#monostate.relops "22.6.9monostate relational operators"), monostate relational operatorsconstexpr bool operator==(monostate, monostate) noexcept; constexpr strong_ordering operator<=>(monostate, monostate) noexcept; // [[variant.specalg]](#specalg "22.6.10Specialized algorithms"), specialized algorithmstemplate<class... Types>constexpr void swap(variant<Types...>&, variant<Types...>&) noexcept(*see below*); // [[variant.bad.access]](#bad.access "22.6.11Class bad_­variant_­access"), class bad_variant_accessclass bad_variant_access; // [[variant.hash]](#hash "22.6.12Hash support"), hash supporttemplate<class T> struct hash; template<class... Types> struct hash<variant<Types...>>; template<> struct hash<monostate>;}
### [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 {template<class... Types>class variant {public:// [[variant.ctor]](#ctor "22.6.3.2Constructors"), constructorsconstexpr 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&&...); // [[variant.dtor]](#dtor "22.6.3.3Destructor"), destructorconstexpr ~variant(); // [[variant.assign]](#assign "22.6.3.4Assignment"), assignmentconstexpr variant& operator=(const variant&); constexpr variant& operator=(variant&&) noexcept(*see below*); template<class T> constexpr variant& operator=(T&&) noexcept(*see below*); // [[variant.mod]](#mod "22.6.3.5Modifiers"), modifierstemplate<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]](#status "22.6.3.6Value status"), value statusconstexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // [[variant.swap]](#swap "22.6.3.7Swap"), swapconstexpr void swap(variant&) noexcept(*see below*); // [[variant.visit]](#visit "22.6.7Visitation"), visitationtemplate<class Self, class Visitor>constexpr decltype(auto) visit(this Self&&, Visitor&&); template<class R, class Self, class Visitor>constexpr 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.1General[variant.variant.general]"),
is nested within ([[intro.object]](intro.object "6.8.2Object 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.2Template 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<T0> 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.6The constexpr and consteval specifiers"))[.](#ctor-6.sentence-1)
The exception specification is equivalent tois_nothrow_default_constructible_v<T0>[.](#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*<j>(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<Ti> is true for all i[.](#ctor-9.sentence-1)
If is_trivially_copy_constructible_v<Ti> 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<Ti> 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*<j>(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<Ti> for all i[.](#ctor-13.sentence-1)
If is_trivially_move_constructible_v<Ti> is true for all i, this constructor is trivial[.](#ctor-13.sentence-2)
[🔗](#lib:variant,constructor___)
`template<class T> 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>(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>(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<remove_cvref_t<T>, variant> is false,
- [(15.3)](#ctor-15.3)
remove_cvref_t<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<Tj, T> is true, and
- [(15.5)](#ctor-15.5)
the expression *FUN*(std::forward<T>(t)) (with *FUN* being the above-mentioned set of
imaginary functions) is well-formed[.](#ctor-15.sentence-1)
[*Note [2](#ctor-note-2)*:
variant<string, string> 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>(t)[.](#ctor-16.sentence-1)
[17](#ctor-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5889)
*Postconditions*: holds_alternative<Tj>(*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<Tj, T>[.](#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<class T, class... Args> constexpr explicit variant(in_place_type_t<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<T, Args...> 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>(args)...[.](#ctor-21.sentence-1)
[22](#ctor-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5923)
*Postconditions*: holds_alternative<T>(*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<class T, class U, class... Args>
constexpr explicit variant(in_place_type_t<T>, initializer_list<U> 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<T, initializer_list<U>&, 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>(args)...[.](#ctor-26.sentence-1)
[27](#ctor-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5956)
*Postconditions*: holds_alternative<T>(*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<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, 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<TI, Args...> 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>(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<size_t I, class U, class... Args>
constexpr explicit variant(in_place_index_t<I>, initializer_list<U> 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<TI, initializer_list<U>&, 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>(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<Ti> 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<Tj> is true oris_nothrow_move_constructible_v<Tj> is false,
equivalent to emplace<j>(*GET*<j>(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<Ti> &&is_copy_assignable_v<Ti> is true for all i[.](#assign-5.sentence-1)
If is_trivially_copy_constructible_v<Ti> &&is_trivially_copy_assignable_v<Ti> &&is_trivially_destructible_v<Ti> 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<Ti> &&is_move_assignable_v<Ti> 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*<j>(std::move(rhs)) to
the value contained in *this[.](#assign-8.3.sentence-1)
- [(8.4)](#assign-8.4)
Otherwise, equivalent to emplace<j>(*GET*<j>(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<Ti> &&is_trivially_move_assignable_v<Ti> &&is_trivially_destructible_v<Ti> is true for all i, this assignment operator is trivial[.](#assign-10.sentence-1)
The exception specification is equivalent tois_nothrow_move_constructible_v<Ti> && is_nothrow_move_assignable_v<Ti> 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<class T> 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>(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>(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<remove_cvref_t<T>, variant> is false,
- [(12.2)](#assign-12.2)
is_assignable_v<Tj&, T> && is_constructible_v<Tj, T> is true, and
- [(12.3)](#assign-12.3)
the expression *FUN*(std::forward<T>(t)) (with *FUN* being the above-mentioned set
of imaginary functions) is well-formed[.](#assign-12.sentence-1)
[*Note [1](#assign-note-1)*:
variant<string, string> 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>(t) to
the value contained in *this[.](#assign-13.1.sentence-1)
- [(13.2)](#assign-13.2)
Otherwise, if is_nothrow_constructible_v<Tj, T> ||!is_nothrow_move_constructible_v<Tj> is true,
equivalent to emplace<j>(std::forward<T>(t))[.](#assign-13.2.sentence-1)
- [(13.3)](#assign-13.3)
Otherwise, equivalent to emplace<j>(Tj(std::forward<T>(t)))[.](#assign-13.3.sentence-1)
[14](#assign-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6211)
*Postconditions*: holds_alternative<Tj>(*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<Tj&, T> && is_nothrow_constructible_v<Tj, T>
- [(16.1)](#assign-16.1)
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[.](#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<class T, class... Args> constexpr T& emplace(Args&&... args);
`
[1](#mod-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6244)
*Constraints*: is_constructible_v<T, Args...> 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<I>(std::forward<Args>(args)...); where I is the zero-based index of T in Types[.](#mod-2.sentence-1)
[🔗](#lib:emplace,variant_)
`template<class T, class U, class... Args>
constexpr T& emplace(initializer_list<U> il, Args&&... args);
`
[3](#mod-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6265)
*Constraints*: is_constructible_v<T, initializer_list<U>&, 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<I>(il, std::forward<Args>(args)...); where I is the zero-based index of T in Types[.](#mod-4.sentence-1)
[🔗](#lib:emplace,variant__)
`template<size_t I, class... Args>
constexpr variant_alternative_t<I, variant<Types...>>& 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<TI, Args...> 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>(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<size_t I, class U, class... Args>
constexpr variant_alternative_t<I, variant<Types...>>&
emplace(initializer_list<U> 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<TI, initializer_list<U>&, 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>(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<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*]
[🔗](#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<Ti> 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.3Swappable requirements[swappable.requirements]") requirements ([[swappable.requirements]](swappable.requirements "16.4.4.3Swappable 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*<i>(*this), *GET*<i>(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*<i>(*this), *GET*<i>(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*<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 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<Ti> && is_nothrow_swappable_v<Ti> for all i[.](#swap-5.sentence-3)
### [22.6.4](#helper) variant helper classes [[variant.helper]](variant.helper)
[🔗](#lib:variant_size)
`template<class T> 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.2Requirements[meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2Requirements"))
with a base characteristic of integral_constant<size_t, N> for some N[.](#helper-1.sentence-1)
[🔗](#lib:variant_size_)
`template<class T> struct variant_size<const T>;
`
[2](#helper-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6468)
Let VS denote variant_size<T> of the cv-unqualified
type T[.](#helper-2.sentence-1)
Then each specialization of the template meets the[*Cpp17UnaryTypeTrait*](meta.rqmts#:Cpp17UnaryTypeTrait "21.3.2Requirements[meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2Requirements")) with a
base characteristic of integral_constant<size_t, VS::value>[.](#helper-2.sentence-2)
[🔗](#lib:variant_size__)
`template<class... Types>
struct variant_size<variant<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
`
[🔗](#lib:variant_alternative)
`template<size_t I, class T> struct variant_alternative<I, const T>;
`
[3](#helper-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6488)
Let VA denote variant_alternative<I, T> of the
cv-unqualified type T[.](#helper-3.sentence-1)
Then each specialization of the template
meets the [*Cpp17TransformationTrait*](meta.rqmts#:Cpp17TransformationTrait "21.3.2Requirements[meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2Requirements")) with a
member typedef type that names the type add_const_t<VA::type>[.](#helper-3.sentence-2)
[🔗](#lib:variant_alternative_)
`variant_alternative<I, variant<Types...>>::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<class T, class... Types>
constexpr bool holds_alternative(const variant<Types...>& 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<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
`
[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<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);
`
[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<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);
`
[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<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;
`
[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<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;
`
[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<i>(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<class... Types>
constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
`
[1](#relops-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6653)
*Constraints*: *GET*<i>(v) == *GET*<i>(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*<i>(v) == *GET*<i>(w) with i being v.index()[.](#relops-2.sentence-1)
[🔗](#lib:operator!=,variant)
`template<class... Types>
constexpr bool operator!=(const variant<Types...>& v, const variant<Types...>& w);
`
[3](#relops-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6672)
*Constraints*: *GET*<i>(v) != *GET*<i>(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*<i>(v) != *GET*<i>(w) with i being v.index()[.](#relops-4.sentence-1)
[🔗](#lib:operator%3c,variant)
`template<class... Types>
constexpr bool operator<(const variant<Types...>& v, const variant<Types...>& w);
`
[5](#relops-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6691)
*Constraints*: *GET*<i>(v) < *GET*<i>(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*<i>(v) < *GET*<i>(w) with i being v.index()[.](#relops-6.sentence-1)
[🔗](#lib:operator%3e,variant)
`template<class... Types>
constexpr bool operator>(const variant<Types...>& v, const variant<Types...>& w);
`
[7](#relops-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6712)
*Constraints*: *GET*<i>(v) > *GET*<i>(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*<i>(v) > *GET*<i>(w) with i being v.index()[.](#relops-8.sentence-1)
[🔗](#lib:operator%3c=,variant)
`template<class... Types>
constexpr bool operator<=(const variant<Types...>& v, const variant<Types...>& w);
`
[9](#relops-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6733)
*Constraints*: *GET*<i>(v) <= *GET*<i>(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*<i>(v) <= *GET*<i>(w) with i being v.index()[.](#relops-10.sentence-1)
[🔗](#lib:operator%3e=,variant)
`template<class... Types>
constexpr bool operator>=(const variant<Types...>& v, const variant<Types...>& w);
`
[11](#relops-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6754)
*Constraints*: *GET*<i>(v) >= *GET*<i>(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*<i>(v) >= *GET*<i>(w) with i being v.index()[.](#relops-12.sentence-1)
[🔗](#lib:operator%3c=%3e,variant)
`template<class... Types> requires ([three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4Concept 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);
`
[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*<i>(v) <=> *GET*<i>(w); with i being v.index()[.](#relops-13.sentence-1)
### [22.6.7](#visit) Visitation [[variant.visit]](variant.visit)
[🔗](#lib: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);
`
[1](#visit-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6802)
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)[.](#visit-1.sentence-2)
For each 0≤i<n, letVi denote the type
decltype(*as-variant*(std::forward<Variantsi>(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<n[.](#visit-2.sentence-1)
[3](#visit-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6823)
Let V denote the pack of types Vi[.](#visit-3.sentence-1)
[4](#visit-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6826)
Let m be a pack of n values of type size_t[.](#visit-4.sentence-1)
Such a pack is valid if
‰¤mi<variant_size_v<remove_reference_t<Vi>> for all 0≤i<n[.](#visit-4.sentence-2)
For each valid pack m, let e(m) denote the expression:*INVOKE*(std::forward<Visitor>(vis), *GET*<m>(std::forward<V>(vars))...) // see [[func.require]](func.require "22.10.4Requirements") for the first form and*INVOKE*<R>(std::forward<Visitor>(vis), *GET*<m>(std::forward<V>(vars))...) // see [[func.require]](func.require "22.10.4Requirements") 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≤i<n[.](#visit-6.sentence-1)
The return type is decltype(e(m)) for the first form[.](#visit-6.sentence-2)
[7](#visit-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6853)
*Throws*: bad_variant_access if(*as-variant*(vars).valueless_by_exception() || ...) is true[.](#visit-7.sentence-1)
[8](#visit-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6859)
*Complexity*: For n ≤ 1, the invocation of the callable object is
implemented in constant time, i.e., for n=1, it does not depend on
the number of alternative types of V0[.](#visit-8.sentence-1)
For n>1, the invocation of the callable object has
no complexity requirements[.](#visit-8.sentence-2)
[🔗](#lib:visit,variant_)
`template<class Self, class Visitor>
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<Self>, variant)) ([[forward]](forward "22.2.4Forward/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.3Names of template specializations[temp.names]") that
begins with a type [*template-argument*](temp.names#nt:template-argument "13.3Names 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<Visitor>(vis), (V)self);
[🔗](#lib:visit,variant__)
`template<class R, class Self, class Visitor>
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<Self>, variant)) ([[forward]](forward "22.2.4Forward/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<R>(std::forward<Visitor>(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<class... Types>
constexpr void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below);
`
[1](#specalg-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6947)
*Constraints*: is_move_constructible_v<Ti> && is_swappable_v<Ti> 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.3Class 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.3Character literals"))[.](#bad.access-2.sentence-1)
### [22.6.12](#hash) Hash support [[variant.hash]](variant.hash)
[🔗](#lib:hash,variant)
`template<class... Types> struct hash<variant<Types...>>;
`
[1](#hash-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6999)
The specialization hash<variant<Types...>> is enabled ([[unord.hash]](unord.hash "22.10.19Class template hash"))
if and only if every specialization in hash<remove_const_t<Types>>... 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<monostate>;
`
[2](#hash-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L7011)
The specialization is enabled ([[unord.hash]](unord.hash "22.10.19Class template hash"))[.](#hash-2.sentence-1)