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

890 lines
34 KiB
Markdown
Raw 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.variant]
# 22 General utilities library [[utilities]](./#utilities)
## 22.6 Variants [[variant]](variant#variant)
### 22.6.3 Class template variant [variant.variant]
#### [22.6.3.1](#general) General [[variant.variant.general]](variant.variant.general)
namespace std {template<class... Types>class variant {public:// [[variant.ctor]](#variant.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]](#variant.dtor "22.6.3.3Destructor"), destructorconstexpr ~variant(); // [[variant.assign]](#variant.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]](#variant.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]](#variant.status "22.6.3.6Value status"), value statusconstexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // [[variant.swap]](#variant.swap "22.6.3.7Swap"), swapconstexpr void swap(variant&) noexcept(*see below*); // [[variant.visit]](variant.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](#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[.](#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[.](#general-1.sentence-2)
[2](#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"))[.](#general-2.sentence-1)
[3](#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[.](#general-3.sentence-1)
[4](#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[.](#general-4.sentence-1)
#### [22.6.3.2](#variant.ctor) Constructors [[variant.ctor]](variant.ctor)
[1](#variant.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[.](#variant.ctor-1.sentence-1)
[🔗](#lib:variant,constructor)
`constexpr variant() noexcept(see below);
`
[2](#variant.ctor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5755)
*Constraints*: is_default_constructible_v<T0> is true[.](#variant.ctor-2.sentence-1)
[3](#variant.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[.](#variant.ctor-3.sentence-1)
[4](#variant.ctor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5763)
*Postconditions*: valueless_by_exception() is false and index() is 0[.](#variant.ctor-4.sentence-1)
[5](#variant.ctor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5767)
*Throws*: Any exception thrown by the value-initialization of T0[.](#variant.ctor-5.sentence-1)
[6](#variant.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"))[.](#variant.ctor-6.sentence-1)
The exception specification is equivalent tois_nothrow_default_constructible_v<T0>[.](#variant.ctor-6.sentence-2)
[*Note [1](#variant.ctor-note-1)*:
See also class monostate[.](#variant.ctor-6.sentence-3)
— *end note*]
[🔗](#lib:variant,constructor_)
`constexpr variant(const variant& w);
`
[7](#variant.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()[.](#variant.ctor-7.sentence-1)
Otherwise, initializes the variant to not hold a value[.](#variant.ctor-7.sentence-2)
[8](#variant.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[.](#variant.ctor-8.sentence-1)
[9](#variant.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[.](#variant.ctor-9.sentence-1)
If is_trivially_copy_constructible_v<Ti> is true for all i, this constructor is trivial[.](#variant.ctor-9.sentence-2)
[🔗](#lib:variant,constructor__)
`constexpr variant(variant&& w) noexcept(see below);
`
[10](#variant.ctor-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5814)
*Constraints*: is_move_constructible_v<Ti> is true for all i[.](#variant.ctor-10.sentence-1)
[11](#variant.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()[.](#variant.ctor-11.sentence-1)
Otherwise, initializes the variant to not hold a value[.](#variant.ctor-11.sentence-2)
[12](#variant.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[.](#variant.ctor-12.sentence-1)
[13](#variant.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[.](#variant.ctor-13.sentence-1)
If is_trivially_move_constructible_v<Ti> is true for all i, this constructor is trivial[.](#variant.ctor-13.sentence-2)
[🔗](#lib:variant,constructor___)
`template<class T> constexpr variant(T&& t) noexcept(see below);
`
[14](#variant.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[.](#variant.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[.](#variant.ctor-14.sentence-2)
[15](#variant.ctor-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5854)
*Constraints*:
- [(15.1)](#variant.ctor-15.1)
sizeof...(Types) is nonzero,
- [(15.2)](#variant.ctor-15.2)
is_same_v<remove_cvref_t<T>, variant> is false,
- [(15.3)](#variant.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)](#variant.ctor-15.4)
is_constructible_v<Tj, T> is true, and
- [(15.5)](#variant.ctor-15.5)
the expression *FUN*(std::forward<T>(t)) (with *FUN* being the above-mentioned set of
imaginary functions) is well-formed[.](#variant.ctor-15.sentence-1)
[*Note [2](#variant.ctor-note-2)*:
variant<string, string> v("abc"); is ill-formed, as both alternative types have an equally viable constructor
for the argument[.](#variant.ctor-15.5.sentence-2)
— *end note*]
[16](#variant.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)[.](#variant.ctor-16.sentence-1)
[17](#variant.ctor-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5889)
*Postconditions*: holds_alternative<Tj>(*this) is true[.](#variant.ctor-17.sentence-1)
[18](#variant.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[.](#variant.ctor-18.sentence-1)
[19](#variant.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>[.](#variant.ctor-19.sentence-1)
If Tj's selected constructor is a constexpr constructor,
this constructor is a constexpr constructor[.](#variant.ctor-19.sentence-2)
[🔗](#lib:variant,constructor____)
`template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
`
[20](#variant.ctor-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5911)
*Constraints*:
- [(20.1)](#variant.ctor-20.1)
There is exactly one occurrence of T in Types... and
- [(20.2)](#variant.ctor-20.2)
is_constructible_v<T, Args...> is true[.](#variant.ctor-20.sentence-1)
[21](#variant.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)...[.](#variant.ctor-21.sentence-1)
[22](#variant.ctor-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5923)
*Postconditions*: holds_alternative<T>(*this) is true[.](#variant.ctor-22.sentence-1)
[23](#variant.ctor-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5927)
*Throws*: Any exception thrown by calling the selected constructor of T[.](#variant.ctor-23.sentence-1)
[24](#variant.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[.](#variant.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](#variant.ctor-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5944)
*Constraints*:
- [(25.1)](#variant.ctor-25.1)
There is exactly one occurrence of T in Types... and
- [(25.2)](#variant.ctor-25.2)
is_constructible_v<T, initializer_list<U>&, Args...> is true[.](#variant.ctor-25.sentence-1)
[26](#variant.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)...[.](#variant.ctor-26.sentence-1)
[27](#variant.ctor-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5956)
*Postconditions*: holds_alternative<T>(*this) is true[.](#variant.ctor-27.sentence-1)
[28](#variant.ctor-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5960)
*Throws*: Any exception thrown by calling the selected constructor of T[.](#variant.ctor-28.sentence-1)
[29](#variant.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[.](#variant.ctor-29.sentence-1)
[🔗](#lib:variant,constructor______)
`template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
`
[30](#variant.ctor-30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5976)
*Constraints*:
- [(30.1)](#variant.ctor-30.1)
I is less than sizeof...(Types) and
- [(30.2)](#variant.ctor-30.2)
is_constructible_v<TI, Args...> is true[.](#variant.ctor-30.sentence-1)
[31](#variant.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)...[.](#variant.ctor-31.sentence-1)
[32](#variant.ctor-32)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5990)
*Postconditions*: index() is I[.](#variant.ctor-32.sentence-1)
[33](#variant.ctor-33)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L5994)
*Throws*: Any exception thrown by calling the selected constructor of TI[.](#variant.ctor-33.sentence-1)
[34](#variant.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[.](#variant.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](#variant.ctor-35)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6011)
*Constraints*:
- [(35.1)](#variant.ctor-35.1)
I is less than sizeof...(Types) and
- [(35.2)](#variant.ctor-35.2)
is_constructible_v<TI, initializer_list<U>&, Args...> is true[.](#variant.ctor-35.sentence-1)
[36](#variant.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)...[.](#variant.ctor-36.sentence-1)
[37](#variant.ctor-37)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6025)
*Postconditions*: index() is I[.](#variant.ctor-37.sentence-1)
[38](#variant.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[.](#variant.ctor-38.sentence-1)
#### [22.6.3.3](#variant.dtor) Destructor [[variant.dtor]](variant.dtor)
[🔗](#lib:variant,destructor)
`constexpr ~variant();
`
[1](#variant.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[.](#variant.dtor-1.sentence-1)
[2](#variant.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[.](#variant.dtor-2.sentence-1)
#### [22.6.3.4](#variant.assign) Assignment [[variant.assign]](variant.assign)
[🔗](#lib:operator=,variant)
`constexpr variant& operator=(const variant& rhs);
`
[1](#variant.assign-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6062)
Let j be rhs.index()[.](#variant.assign-1.sentence-1)
[2](#variant.assign-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6065)
*Effects*:
- [(2.1)](#variant.assign-2.1)
If neither *this nor rhs holds a value, there is no effect[.](#variant.assign-2.1.sentence-1)
- [(2.2)](#variant.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[.](#variant.assign-2.2.sentence-1)
- [(2.3)](#variant.assign-2.3)
Otherwise, if index() == j, assigns the value contained in rhs to the value contained in *this[.](#variant.assign-2.3.sentence-1)
- [(2.4)](#variant.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))[.](#variant.assign-2.4.sentence-1)
- [(2.5)](#variant.assign-2.5)
Otherwise, equivalent to operator=(variant(rhs))[.](#variant.assign-2.5.sentence-1)
[3](#variant.assign-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6085)
*Postconditions*: index() == rhs.index()[.](#variant.assign-3.sentence-1)
[4](#variant.assign-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6089)
*Returns*: *this[.](#variant.assign-4.sentence-1)
[5](#variant.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[.](#variant.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[.](#variant.assign-5.sentence-2)
[🔗](#lib:operator=,variant_)
`constexpr variant& operator=(variant&& rhs) noexcept(see below);
`
[6](#variant.assign-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6111)
Let j be rhs.index()[.](#variant.assign-6.sentence-1)
[7](#variant.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[.](#variant.assign-7.sentence-1)
[8](#variant.assign-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6120)
*Effects*:
- [(8.1)](#variant.assign-8.1)
If neither *this nor rhs holds a value, there is no effect[.](#variant.assign-8.1.sentence-1)
- [(8.2)](#variant.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[.](#variant.assign-8.2.sentence-1)
- [(8.3)](#variant.assign-8.3)
Otherwise, if index() == j, assigns *GET*<j>(std::move(rhs)) to
the value contained in *this[.](#variant.assign-8.3.sentence-1)
- [(8.4)](#variant.assign-8.4)
Otherwise, equivalent to emplace<j>(*GET*<j>(std::move(rhs)))[.](#variant.assign-8.4.sentence-1)
[9](#variant.assign-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6135)
*Returns*: *this[.](#variant.assign-9.sentence-1)
[10](#variant.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[.](#variant.assign-10.sentence-1)
The exception specification is equivalent tois_nothrow_move_constructible_v<Ti> && is_nothrow_move_assignable_v<Ti> for all i[.](#variant.assign-10.sentence-2)
- [(10.1)](#variant.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[.](#variant.assign-10.1.sentence-1)
- [(10.2)](#variant.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[.](#variant.assign-10.2.sentence-1)
[🔗](#lib:operator=,variant__)
`template<class T> constexpr variant& operator=(T&& t) noexcept(see below);
`
[11](#variant.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[.](#variant.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[.](#variant.assign-11.sentence-2)
[12](#variant.assign-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6173)
*Constraints*:
- [(12.1)](#variant.assign-12.1)
is_same_v<remove_cvref_t<T>, variant> is false,
- [(12.2)](#variant.assign-12.2)
is_assignable_v<Tj&, T> && is_constructible_v<Tj, T> is true, and
- [(12.3)](#variant.assign-12.3)
the expression *FUN*(std::forward<T>(t)) (with *FUN* being the above-mentioned set
of imaginary functions) is well-formed[.](#variant.assign-12.sentence-1)
[*Note [1](#variant.assign-note-1)*:
variant<string, string> v;
v = "abc"; is ill-formed, as both alternative types have an equally viable constructor
for the argument[.](#variant.assign-12.3.sentence-2)
— *end note*]
[13](#variant.assign-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6197)
*Effects*:
- [(13.1)](#variant.assign-13.1)
If *this holds a Tj, assigns std::forward<T>(t) to
the value contained in *this[.](#variant.assign-13.1.sentence-1)
- [(13.2)](#variant.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))[.](#variant.assign-13.2.sentence-1)
- [(13.3)](#variant.assign-13.3)
Otherwise, equivalent to emplace<j>(Tj(std::forward<T>(t)))[.](#variant.assign-13.3.sentence-1)
[14](#variant.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[.](#variant.assign-14.sentence-1)
[15](#variant.assign-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6216)
*Returns*: *this[.](#variant.assign-15.sentence-1)
[16](#variant.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)](#variant.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[.](#variant.assign-16.1.sentence-1)
- [(16.2)](#variant.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[.](#variant.assign-16.2.sentence-1)
#### [22.6.3.5](#variant.mod) Modifiers [[variant.mod]](variant.mod)
[🔗](#lib:emplace,variant)
`template<class T, class... Args> constexpr T& emplace(Args&&... args);
`
[1](#variant.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[.](#variant.mod-1.sentence-1)
[2](#variant.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[.](#variant.mod-2.sentence-1)
[🔗](#lib:emplace,variant_)
`template<class T, class U, class... Args>
constexpr T& emplace(initializer_list<U> il, Args&&... args);
`
[3](#variant.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[.](#variant.mod-3.sentence-1)
[4](#variant.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[.](#variant.mod-4.sentence-1)
[🔗](#lib:emplace,variant__)
`template<size_t I, class... Args>
constexpr variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
`
[5](#variant.mod-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6286)
*Mandates*: I < sizeof...(Types)[.](#variant.mod-5.sentence-1)
[6](#variant.mod-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6290)
*Constraints*: is_constructible_v<TI, Args...> is true[.](#variant.mod-6.sentence-1)
[7](#variant.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[.](#variant.mod-7.sentence-1)
Then direct-non-list-initializes the contained value of type TI with the arguments std::forward<Args>(args)...[.](#variant.mod-7.sentence-2)
[8](#variant.mod-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6301)
*Postconditions*: index() is I[.](#variant.mod-8.sentence-1)
[9](#variant.mod-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6305)
*Returns*: A reference to the new contained value[.](#variant.mod-9.sentence-1)
[10](#variant.mod-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6309)
*Throws*: Any exception thrown during the initialization of the contained value[.](#variant.mod-10.sentence-1)
[11](#variant.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[.](#variant.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](#variant.mod-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6327)
*Mandates*: I < sizeof...(Types)[.](#variant.mod-12.sentence-1)
[13](#variant.mod-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6331)
*Constraints*: is_constructible_v<TI, initializer_list<U>&, Args...> is true[.](#variant.mod-13.sentence-1)
[14](#variant.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[.](#variant.mod-14.sentence-1)
Then direct-non-list-initializes the contained value of type TI with il, std::forward<Args>(args)...[.](#variant.mod-14.sentence-2)
[15](#variant.mod-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6342)
*Postconditions*: index() is I[.](#variant.mod-15.sentence-1)
[16](#variant.mod-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6346)
*Returns*: A reference to the new contained value[.](#variant.mod-16.sentence-1)
[17](#variant.mod-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6350)
*Throws*: Any exception thrown during the initialization of the contained value[.](#variant.mod-17.sentence-1)
[18](#variant.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[.](#variant.mod-18.sentence-1)
#### [22.6.3.6](#variant.status) Value status [[variant.status]](variant.status)
[🔗](#lib:valueless_by_exception,variant)
`constexpr bool valueless_by_exception() const noexcept;
`
[1](#variant.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[.](#variant.status-1.sentence-1)
[2](#variant.status-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6372)
[*Note [1](#variant.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[.](#variant.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](#variant.status-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6393)
*Effects*: If valueless_by_exception() is true, returns variant_npos[.](#variant.status-3.sentence-1)
Otherwise, returns the zero-based index of the alternative of the contained value[.](#variant.status-3.sentence-2)
#### [22.6.3.7](#variant.swap) Swap [[variant.swap]](variant.swap)
[🔗](#lib:swap,variant)
`constexpr void swap(variant& rhs) noexcept(see below);
`
[1](#variant.swap-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6407)
*Mandates*: is_move_constructible_v<Ti> is true for all i[.](#variant.swap-1.sentence-1)
[2](#variant.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"))[.](#variant.swap-2.sentence-1)
[3](#variant.swap-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/utilities.tex#L6415)
*Effects*:
- [(3.1)](#variant.swap-3.1)
If valueless_by_exception() && rhs.valueless_by_exception() no effect[.](#variant.swap-3.1.sentence-1)
- [(3.2)](#variant.swap-3.2)
Otherwise, if index() == rhs.index(), calls swap(*GET*<i>(*this), *GET*<i>(rhs)) where i is index()[.](#variant.swap-3.2.sentence-1)
- [(3.3)](#variant.swap-3.3)
Otherwise, exchanges values of rhs and *this[.](#variant.swap-3.3.sentence-1)
[4](#variant.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()[.](#variant.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()[.](#variant.swap-4.sentence-2)
[5](#variant.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()[.](#variant.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[.](#variant.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[.](#variant.swap-5.sentence-3)