22 General utilities library [utilities]
namespace std {
  template<class... Types>
  class variant {
  public:
    
    constexpr variant() noexcept(see below);
    constexpr variant(const variant&);
    constexpr variant(variant&&) noexcept(see below);
    template<class T>
      constexpr variant(T&&) noexcept(see below);
    template<class T, class... Args>
      constexpr explicit variant(in_place_type_t<T>, Args&&...);
    template<class T, class U, class... Args>
      constexpr explicit variant(in_place_type_t<T>, initializer_list<U>, Args&&...);
    template<size_t I, class... Args>
      constexpr explicit variant(in_place_index_t<I>, Args&&...);
    template<size_t I, class U, class... Args>
      constexpr explicit variant(in_place_index_t<I>, initializer_list<U>, Args&&...);
    
    constexpr ~variant();
    
    constexpr variant& operator=(const variant&);
    constexpr variant& operator=(variant&&) noexcept(see below);
    template<class T> constexpr variant& operator=(T&&) noexcept(see below);
    
    template<class T, class... Args>
      constexpr T& emplace(Args&&...);
    template<class T, class U, class... Args>
      constexpr T& emplace(initializer_list<U>, Args&&...);
    template<size_t I, class... Args>
      constexpr variant_alternative_t<I, variant<Types...>>& emplace(Args&&...);
    template<size_t I, class U, class... Args>
      constexpr variant_alternative_t<I, variant<Types...>>&
        emplace(initializer_list<U>, Args&&...);
    
    constexpr bool valueless_by_exception() const noexcept;
    constexpr size_t index() const noexcept;
    
    constexpr void swap(variant&) noexcept(see below);
    
    template<class Self, class Visitor>
      constexpr decltype(auto) visit(this Self&&, Visitor&&);
    template<class R, class Self, class Visitor>
      constexpr R visit(this Self&&, Visitor&&);
  };
}
Any instance of 
variant at any given time either holds a value
of one of its alternative types or holds no value
.  When an instance of 
variant holds a value of alternative type 
T,
it means that a value of type 
T, referred to as the 
variant
object's 
contained value,
is nested within (
[intro.object]) the
variant object
.A program that instantiates the definition of 
variant with
no template arguments is ill-formed
.If a program declares an explicit or partial specialization of 
variant,
the program is ill-formed, no diagnostic required
.In the descriptions that follow, let 
i be in the range [
0, sizeof...(Types)),
and 
Ti be the 
ith type in 
Types.constexpr variant() noexcept(see below);
Constraints: 
is_default_constructible_v<T0> is 
true. Effects: Constructs a 
variant holding a value-initialized value of type 
T0. Postconditions: 
valueless_by_exception() is 
false and 
index() is 
0. Throws: Any exception thrown by the value-initialization of 
T0. Remarks: This function is 
constexpr if and only if the
value-initialization of the alternative type 
T0
would be constexpr-suitable (
[dcl.constexpr])
.  The exception specification is equivalent to
is_nothrow_default_constructible_v<T0>.  [
Note 1: 
See also class 
monostate. — 
end note]
constexpr variant(const variant& w);
Effects: If 
w holds a value, initializes the 
variant to hold the same
alternative as 
w and direct-initializes the contained value
with 
GET<j>(w), where 
j is 
w.index().  Otherwise, initializes the 
variant to not hold a value
.Throws: Any exception thrown by direct-initializing any 
Ti for all 
i. Remarks: This constructor is defined as deleted unless
is_copy_constructible_v<Ti> is 
true for all 
i.  If 
is_trivially_copy_constructible_v<Ti>
is 
true for all 
i, this constructor is trivial
.constexpr variant(variant&& w) noexcept(see below);
Constraints: 
is_move_constructible_v<Ti> is 
true for all 
i. Effects: If 
w holds a value, initializes the 
variant to hold the same
alternative as 
w and direct-initializes the contained value with
GET<j>(std::move(w)), where 
j is 
w.index().  Otherwise, initializes the 
variant to not hold a value
.Throws: Any exception thrown by move-constructing any 
Ti for all 
i. Remarks: The exception specification is equivalent to the logical 
and of
is_nothrow_move_constructible_v<Ti> for all 
i.  If 
is_trivially_move_constructible_v<Ti>
is 
true for all 
i, this constructor is trivial
.template<class T> constexpr variant(T&& t) noexcept(see below);
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.  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
.Constraints: 
- sizeof...(Types) is nonzero,
 - is_same_v<remove_cvref_t<T>, variant> is false,
 - remove_cvref_t<T> is neither
a specialization of in_place_type_t nor
a specialization of in_place_index_t,
 - is_constructible_v<Tj, T> is true, and
 - the expression FUN(std::forward<T>(t))
(with FUN being the above-mentioned set of
imaginary functions) is well-formed. 
[
Note 2: 
variant<string, string> v("abc");
is ill-formed, as both alternative types have an equally viable constructor
for the argument
.  — 
end note]
 
 Effects: Initializes 
*this to hold the alternative type 
Tj and
direct-non-list-initializes the contained value with 
std::forward<T>(t). Postconditions: 
holds_alternative<Tj>(*this) is 
true. Throws: Any exception thrown by the initialization of the selected alternative 
Tj. Remarks: The exception specification is equivalent to
is_nothrow_constructible_v<Tj, T>.  If 
Tj's selected constructor is a constexpr constructor,
this constructor is a constexpr constructor
.template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
Constraints: 
- There is exactly one occurrence of T in Types... and
 - is_constructible_v<T, Args...> is true.
 
 Effects: Direct-non-list-initializes the contained value of type 
T
with 
std::forward<Args>(args).... Postconditions: 
holds_alternative<T>(*this) is 
true. Throws: Any exception thrown by calling the selected constructor of 
T. Remarks: If 
T's selected constructor is a constexpr constructor, this
constructor is a constexpr constructor
. template<class T, class U, class... Args>
  constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Constraints: 
- There is exactly one occurrence of T in Types... and
 - is_constructible_v<T, initializer_list<U>&, Args...> is true.
 
 Effects: Direct-non-list-initializes the contained value of type 
T
with 
il, std::forward<Args>(args).... Postconditions: 
holds_alternative<T>(*this) is 
true. Throws: Any exception thrown by calling the selected constructor of 
T. Remarks: If 
T's selected constructor is a constexpr constructor, this
constructor is a constexpr constructor
. template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
Constraints: 
- I is less than sizeof...(Types) and
 - is_constructible_v<TI, Args...> is true.
 
 Effects: Direct-non-list-initializes the contained value of type 
TI
with 
std::forward<Args>(args).... Postconditions: 
index() is 
I. Throws: Any exception thrown by calling the selected constructor of 
TI. Remarks: If 
TI's selected constructor is a constexpr constructor, this
constructor is a constexpr constructor
. template<size_t I, class U, class... Args>
  constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);
Constraints: 
- I is less than sizeof...(Types) and
 - is_constructible_v<TI, initializer_list<U>&, Args...> is true.
 
 Effects: Direct-non-list-initializes the contained value of type 
TI
with 
il, std::forward<Args>(args).... Postconditions: 
index() is 
I. Remarks: If 
TI's selected constructor is a constexpr constructor, this
constructor is a constexpr constructor
. Effects: If 
valueless_by_exception() is 
false,
destroys the currently contained value
. Remarks: If 
is_trivially_destructible_v<Ti> is 
true for all 
Ti,
then this destructor is trivial
. constexpr variant& operator=(const variant& rhs);
Effects: 
If neither 
*this nor 
rhs holds a value, there is no effect
.Otherwise, if 
*this holds a value but 
rhs does not, destroys the value
contained in 
*this and sets 
*this to not hold a value
.Otherwise, if 
index() == j, assigns the value contained in 
rhs
to the value contained in 
*this.Otherwise, if either 
is_nothrow_copy_constructible_v<Tj>
is 
true or
is_nothrow_move_constructible_v<Tj> is 
false,
equivalent to 
emplace<j>(GET<j>(rhs)).Otherwise, equivalent to 
operator=(variant(rhs)).
 Postconditions: 
index() == rhs.index(). Remarks: This operator is defined as deleted unless
is_copy_constructible_v<Ti> &&
is_copy_assignable_v<Ti>
is 
true for all 
i.  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
.constexpr variant& operator=(variant&& rhs) noexcept(see below);
Constraints: 
is_move_constructible_v<Ti> &&
is_move_assignable_v<Ti> is
true for all 
i. Effects: 
If neither 
*this nor 
rhs holds a value, there is no effect
.Otherwise, if 
*this holds a value but 
rhs does not, destroys the value
contained in 
*this and sets 
*this to not hold a value
.Otherwise, if 
index() == j, assigns 
GET<j>(std::move(rhs)) to
the value contained in 
*this.Otherwise, equivalent to 
emplace<j>(GET<j>(std::move(rhs))).
 Remarks: If 
is_trivially_move_constructible_v<Ti> &&
is_trivially_move_assignable_v<Ti> &&
is_trivially_destructible_v<Ti>
is 
true for all 
i, this assignment operator is trivial
.  The exception specification is equivalent to
is_nothrow_move_constructible_v<Ti> && is_nothrow_move_assignable_v<Ti> for all 
i.  If an exception is thrown during the call to 
Tj's move construction
(with 
j being 
rhs.index()), the 
variant will hold no value
.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.
template<class T> constexpr variant& operator=(T&& t) noexcept(see below);
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.  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
.Constraints: 
- is_same_v<remove_cvref_t<T>, variant> is false,
 - is_assignable_v<Tj&, T> && is_constructible_v<Tj, T>
is true, and
 - the expression FUN(std::forward<T>(t))
(with FUN being the above-mentioned set
of imaginary functions) is well-formed. 
[
Note 1: 
variant<string, string> v;
v = "abc";
is ill-formed, as both alternative types have an equally viable constructor
for the argument
.  — 
end note]
 
 Effects: 
If 
*this holds a 
Tj, assigns 
std::forward<T>(t) to
the value contained in 
*this.Otherwise, if 
is_nothrow_constructible_v<Tj, T> ||
!is_nothrow_move_constructible_v<Tj> is 
true,
equivalent to 
emplace<j>(std::forward<T>(t)).Otherwise, equivalent to 
emplace<j>(Tj(std::forward<T>(t))).
 Postconditions: 
holds_alternative<Tj>(*this) is 
true, with 
Tj
selected by the imaginary function overload resolution described above
. Remarks: The exception specification is equivalent to:
is_nothrow_assignable_v<Tj&, T> && is_nothrow_constructible_v<Tj, T>
If an exception is thrown during the assignment of 
std::forward<T>(t)
to the value contained in 
*this, the state of the contained value and
t are as defined by the exception safety guarantee of the assignment
expression; 
valueless_by_exception() will be 
false.If an exception is thrown during the initialization of the contained value,
the 
variant object is permitted to not hold a value
.
 template<class T, class... Args> constexpr T& emplace(Args&&... args);
Constraints: 
is_constructible_v<T, Args...> is 
true, and
T occurs exactly once in 
Types. Effects: Equivalent to:
return emplace<I>(std::forward<Args>(args)...);
where 
I is the zero-based index of 
T in 
Types. template<class T, class U, class... Args>
  constexpr T& emplace(initializer_list<U> il, Args&&... args);
Constraints: 
is_constructible_v<T, initializer_list<U>&, Args...> is 
true,
and 
T occurs exactly once in 
Types. Effects: Equivalent to:
return emplace<I>(il, std::forward<Args>(args)...);
where 
I is the zero-based index of 
T in 
Types. template<size_t I, class... Args>
  constexpr variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
Mandates: 
I < sizeof...(Types). Constraints: 
is_constructible_v<TI, Args...> is 
true. Effects: Destroys the currently contained value if 
valueless_by_exception()
is 
false.  Then direct-non-list-initializes the contained value of type 
TI
with the arguments 
std::forward<Args>(args)....Postconditions: 
index() is 
I. Returns: A reference to the new contained value
. Throws: Any exception thrown during the initialization of the contained value
. Remarks: If an exception is thrown during the initialization of the contained value,
the 
variant is permitted to not hold a value
. template<size_t I, class U, class... Args>
  constexpr variant_alternative_t<I, variant<Types...>>&
    emplace(initializer_list<U> il, Args&&... args);
Mandates: 
I < sizeof...(Types). Constraints: 
is_constructible_v<TI, initializer_list<U>&, Args...> is 
true. Effects: Destroys the currently contained value if 
valueless_by_exception()
is 
false.  Then direct-non-list-initializes the contained value of type 
TI
with 
il, std::forward<Args>(args)....Postconditions: 
index() is 
I. Returns: A reference to the new contained value
. Throws: Any exception thrown during the initialization of the contained value
. Remarks: If an exception is thrown during the initialization of the contained value,
the 
variant is permitted to not hold a value
. constexpr bool valueless_by_exception() const noexcept;
Effects: Returns 
false if and only if the 
variant holds a value
. [
Note 1: 
It is possible for a 
variant to hold no value
if an exception is thrown during a
type-changing assignment or emplacement
.  The latter means that even a
variant<float, int> can become valueless_by_exception(), for
instance by
struct S { operator int() { throw 42; }};
variant<float, int> v{12.f};
v.emplace<1>(S());
 — 
end note]
constexpr size_t index() const noexcept;
Effects: If 
valueless_by_exception() is 
true, returns 
variant_npos.  Otherwise, returns the zero-based index of the alternative of the contained value
.constexpr void swap(variant& rhs) noexcept(see below);
Mandates: 
is_move_constructible_v<Ti> is 
true for all 
i. Effects: 
If 
valueless_by_exception() && rhs.valueless_by_exception() no effect
.Otherwise, if 
index() == rhs.index(), calls 
swap(GET<i>(*this), GET<i>(rhs)) where 
i is 
index().Otherwise, exchanges values of 
rhs and 
*this.
 Throws: If 
index() == rhs.index(),
any exception thrown by 
swap(GET<i>(*this), GET<i>(rhs))
with 
i being 
index().  Otherwise, any exception thrown by the move constructor
of 
Ti or 
Tj
with 
i being 
index() and 
j being 
rhs.index().Remarks: If an exception is thrown during the call to function 
swap(GET<i>(*this), GET<i>(rhs)),
the states of the contained values of 
*this and of 
rhs are
determined by the exception safety guarantee of 
swap for lvalues of
Ti with 
i being 
index().  If an exception is thrown during the exchange of the values of 
*this
and 
rhs, the states of the values of 
*this and of 
rhs
are determined by the exception safety guarantee of 
variant's move constructor
.  The exception specification is equivalent to the logical 
and of
is_nothrow_move_constructible_v<Ti> && is_nothrow_swappable_v<Ti> for all 
i.