|
|
|
template<class... TTypes>
constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
7
Returns: tuple<TTypes&...>(t...). When an argument in t is ignore, assigning any value to the
corresponding tuple element has no effect.
8
[Example: tie functions allow one to create tuples that unpack tuples into variables. ignore can be
used for elements that are not needed:
int i; std::string s;
tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
// i == 42, s == "C++"
— end example ]
template<class... Tuples>
constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
9
In the following paragraphs, let Ti be the ith type in Tuples, Ui be remove_reference_t<Ti>, and tpi
be the ith parameter in the function parameter pack tpls, where all indexing is zero-based.
10
Requires: For all i, Ui shall be the type cvi tuple<Argsi...>, where cvi is the (possibly empty) ith
cv-qualifier-seq and Argsi is the parameter pack representing the element types in Ui. Let Aik be the
kth type in Argsi. For all Aik the following requirements shall be satisfied:
(10.1)
—
If Ti is deduced as an lvalue reference type, then is_constructible_v<Aik , cvi Aik &> == true,
otherwise
(10.2)
—
is_constructible_v<Aik , cvi Aik &&> == true.
11
Remarks: The types in CTypes shall be equal to the ordered sequence of the extended types Args0...,
Args1..., . . . , Argsn−1..., where n is equal to sizeof...(Tuples). Let ei... be the ith ordered
sequence of tuple elements of the resulting tuple object corresponding to the type sequence Argsi.
12
Returns: A tuple object constructed by initializing the kith type element eik in ei... with
get<ki>(std::forward<Ti>(tpi))
for each valid ki and each group ei in order.
13
[Note: An implementation may support additional types in the parameter pack Tuples that support
the tuple-like protocol, such as pair and array.
— end note ]
23.5.3.5
Calling a function with a tuple of arguments
[tuple.apply]
template<class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t);
1
Effects: Given the exposition-only function:
template<class F, class Tuple, size_t... I>
constexpr decltype(auto)
apply_impl(F&& f, Tuple&& t, index_sequence<I...>) {
// exposition only
return INVOKE(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
// see 23.14.3
}
Equivalent to:
return apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
template<class T, class Tuple>
constexpr T make_from_tuple(Tuple&& t);
2
Effects: Given the exposition-only function:
template<class T, class Tuple, size_t... I>
constexpr T make_from_tuple_impl(Tuple&& t, index_sequence<I...>) {
// exposition only
return T(get<I>(std::forward<Tuple>(t))...);
}
Equivalent to:
§ 23.5.3.5
502
return make_from_tuple_impl<T>(
forward<Tuple>(t),
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
[Note: The type of T must be supplied as an explicit template parameter, as it cannot be deduced
from the argument list.
— end note ]
23.5.3.6
Tuple helper classes
[tuple.helper]
template<class T> struct tuple_size;
1
Remarks: All specializations of tuple_size shall meet the UnaryTypeTrait requirements (23.15.1)
with a base characteristic of integral_constant<size_t, N> for some N.
template<class... Types>
class tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class... Types>
class tuple_element<I, tuple<Types...>> {
public:
using type = TI;
};
2
Requires: I < sizeof...(Types). The program is ill-formed if I is out of bounds.
3
Type: TI is the type of the Ith element of Types, where indexing is zero-based.
template<class T> class tuple_size<const T>;
template<class T> class tuple_size<volatile T>;
template<class T> class tuple_size<const volatile T>;
4
Let TS denote tuple_size<T> of the cv-unqualified type T. If the expression TS ::value is well-
formed when treated as an unevaluated operand, then each of the three templates shall meet the
UnaryTypeTrait requirements (23.15.1) with a base characteristic of
integral_constant<size_t, TS ::value>
Otherwise, they shall have no member value.
5
Access checking is performed as if in a context unrelated to TS and T. Only the validity of the immediate
context of the expression is considered. [Note: The compilation of the expression can result in side
effects such as the instantiation of class template specializations and function template specializations,
the generation of implicitly-defined functions, and so on. Such side effects are not in the “immediate
context” and can result in the program being ill-formed.
— end note ]
6
In addition to being available via inclusion of the <tuple> header, the three templates are available
when either of the headers <array> or <utility> are included.
template<size_t I, class T> class tuple_element<I, const T>;
template<size_t I, class T> class tuple_element<I, volatile T>;
template<size_t I, class T> class tuple_element<I, const volatile T>;
7
Let TE denote tuple_element_t<I, T> of the cv-unqualified type T. Then each of the three templates
shall meet the TransformationTrait requirements (23.15.1) with a member typedef type that names
the following type:
(7.1)
—
for the first specialization, add_const_t<TE >,
(7.2)
—
for the second specialization, add_volatile_t<TE >, and
(7.3)
—
for the third specialization, add_cv_t<TE >.
8
In addition to being available via inclusion of the <tuple> header, the three templates are available
when either of the headers <array> or <utility> are included.
23.5.3.7
Element access
[tuple.elem]
template<size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&
get(tuple<Types...>& t) noexcept;
§ 23.5.3.7
503
template<size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&&
get(tuple<Types...>&& t) noexcept;
// Note A
template<size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&
get(const tuple<Types...>& t) noexcept;
// Note B
template<size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
1
Requires: I < sizeof...(Types). The program is ill-formed if I is out of bounds.
2
Returns: A reference to the Ith element of t, where indexing is zero-based.
3
[Note A: If a T in Types is some reference type X&, the return type is X&, not X&&. However, if the
element type is a non-reference type T, the return type is T&&.
— end note ]
4
[Note B: Constness is shallow. If a T in Types is some reference type X&, the return type is X&, not
const X&. However, if the element type is a non-reference type T, the return type is const T&. This is
consistent with how constness is defined to work for member variables of reference type.
— end note ]
template<class T, class... Types>
constexpr T& get(tuple<Types...>& t) noexcept;
template<class T, class... Types>
constexpr T&& get(tuple<Types...>&& t) noexcept;
template<class T, class... Types>
constexpr const T& get(const tuple<Types...>& t) noexcept;
template<class T, class... Types>
constexpr const T&& get(const tuple<Types...>&& t) noexcept;
5
Requires: The type T occurs exactly once in Types
Otherwise, the program is ill-formed.
6
Returns: A reference to the element of t corresponding to the type T in Types
7
[ Example:
const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
const int& i1 = get<int>(t);
// OK. Not ambiguous. i1 == 1
const int& i2 = get<const int>(t);
// OK. Not ambiguous. i2 == 2
const double& d = get<double>(t);
// ERROR. ill-formed
— end example ]
8
[ Note: The reason get is a non-member function is that if this functionality had been provided as a member
function, code where the type depended on a template parameter would have required using the template
keyword. — end note ]
23.5.3.8
Relational operators
[tuple.rel]
template<class... TTypes, class... UTypes>
constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
1
Requires: For all i, where 0 <= i and i < sizeof...(TTypes), get<i>(t) == get<i>(u) is a valid
expression returning a type that is convertible to bool. sizeof...(TTypes) == sizeof...(UTypes).
2
Returns: true if get<i>(t) == get<i>(u) for all i, otherwise false. For any two zero-length tuples
e and f, e == f returns true.
3
Effects: The elementary comparisons are performed in order from the zeroth index upwards. No
comparisons or element accesses are performed after the first equality comparison that evaluates to
false.
template<class... TTypes, class... UTypes>
constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
4
Requires: For all i, where 0 <= i and i < sizeof...(TTypes), both get<i>(t) < get<i>(u)
and get<i>(u) < get<i>(t) are valid expressions returning types that are convertible to bool.
sizeof...(TTypes) == sizeof...(UTypes).
5
Returns: The result of a lexicographical comparison between t and u. The result is defined as:
(bool)(get<0>(t) < get<0>(u)) || (!(bool)(get<0>(u) < get<0>(t)) && ttail < utail), where
§ 23.5.3.8
504
rtail for some tuple r is a tuple containing all but the first element of r. For any two zero-length tuples
e and f, e < f returns false.
template<class... TTypes, class... UTypes>
constexpr bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
6
Returns: !(t == u).
template<class... TTypes, class... UTypes>
constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
7
Returns: u < t.
template<class... TTypes, class... UTypes>
constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
8
Returns: !(u < t).
template<class... TTypes, class... UTypes>
constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
9
Returns: !(t < u).
10
[ Note: The above definitions for comparison functions do not require ttail (or utail) to be constructed. It may
not even be possible, as t and u are not required to be copy constructible. Also, all comparison functions are
short circuited; they do not perform element accesses beyond what is required to determine the result of the
comparison.
— end note ]
23.5.3.9
Tuple traits
[tuple.traits]
template<class... Types, class Alloc>
struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
1
Requires: Alloc shall be an Allocator (20.5.3.5).
2
[Note: Specialization of this trait informs other library components that tuple can be constructed
with an allocator, even though it does not have a nested allocator_type.
— end note ]
23.5.3.10
Tuple specialized algorithms
[tuple.special]
template<class... Types>
void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below );
1
Remarks: This function shall not participate in overload resolution unless is_swappable_v<Ti> is true
for all i, where 0 ≤ i < sizeof...(Types). The expression inside noexcept is equivalent to:
noexcept(x.swap(y))
2
Effects: As if by x.swap(y).
23.6
Optional objects
[optional]
23.6.1
In general
[optional.general]
1
This subclause describes class template optional that represents optional objects. An optional object is an
object that contains the storage for another object and manages the lifetime of this contained object, if any.
The contained object may be initialized after the optional object has been initialized, and may be destroyed
before the optional object has been destroyed. The initialization state of the contained object is tracked by
the optional object.
23.6.2
Header <optional> synopsis
[optional.syn]
namespace std {
// 23.6.3, class template optional
template<class T>
class optional;
// 23.6.4, no-value state indicator
struct nullopt_t{see below };
inline constexpr nullopt_t nullopt(unspecified );
§ 23.6.2
505
// 23.6.5, class bad_optional_access
class bad_optional_access;
// 23.6.6, relational operators
template<class T, class U>
constexpr bool operator==(const optional<T>&, const optional<U>&);
template<class T, class U>
constexpr bool operator!=(const optional<T>&, const optional<U>&);
template<class T, class U>
constexpr bool operator<(const optional<T>&, const optional<U>&);
template<class T, class U>
constexpr bool operator>(const optional<T>&, const optional<U>&);
template<class T, class U>
constexpr bool operator<=(const optional<T>&, const optional<U>&);
template<class T, class U>
constexpr bool operator>=(const optional<T>&, const optional<U>&);
// 23.6.7, comparison with nullopt
template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
// 23.6.8, comparison with T
template<class T, class U> constexpr bool operator==(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator==(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator<(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator<(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator>(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator>(const T&, const optional<U>&);
template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&);
template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&);
// 23.6.9, specialized algorithms
template<class T>
void swap(optional<T>&, optional<T>&) noexcept(see below );
template<class T>
constexpr optional<see below > make_optional(T&&);
template<class T, class... Args>
constexpr optional<T> make_optional(Args&&... args);
template<class T, class U, class... Args>
constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
// 23.6.10, hash support
template<class T> struct hash;
template<class T> struct hash<optional<T>>;
}
1
A program that necessitates the instantiation of template optional for a reference type, or for possibly
cv-qualified types in_place_t or nullopt_t is ill-formed.
§ 23.6.2
506
23.6.3
Class template optional
[optional.optional]
template<class T>
class optional {
public:
using value_type = T;
// 23.6.3.1, constructors
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
constexpr optional(const optional&);
constexpr optional(optional&&) noexcept(see below );
template<class... Args>
constexpr explicit optional(in_place_t, Args&&...);
template<class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U>,
Args&&...);
template<class U = T>
EXPLICIT constexpr optional(U&&);
template<class U>
EXPLICIT optional(const optional<U>&);
template<class U>
EXPLICIT optional(optional<U>&&);
// 23.6.3.2, destructor
~optional();
// 23.6.3.3, assignment
optional& operator=(nullopt_t) noexcept;
optional& operator=(const optional&);
optional& operator=(optional&&) noexcept(see below );
template<class U = T> optional& operator=(U&&);
template<class U> optional& operator=(const optional<U>&);
template<class U> optional& operator=(optional<U>&&);
template<class... Args> T& emplace(Args&&...);
template<class U, class... Args> T& emplace(initializer_list<U>,
Args&&...);
// 23.6.3.4, swap
void swap(optional&) noexcept(see below );
// 23.6.3.5, observers
constexpr const T* operator->() const;
constexpr T* operator->();
constexpr const T& operator*() const&;
constexpr T& operator*() &;
constexpr T&& operator*() &&;
constexpr const T&& operator*() const&&;
constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr const T& value() const&;
constexpr T& value() &;
constexpr T&& value() &&;
constexpr const T&& value() const&&;
template<class U> constexpr T value_or(U&&) const&;
template<class U> constexpr T value_or(U&&) &&;
// 23.6.3.6, modifiers
void reset() noexcept;
private:
T *val; // exposition only
};
template<class T> optional(T) -> optional<T>;
§ 23.6.3
507
1
Any instance of optional<T> at any given time either contains a value or does not contain a value. When
an instance of optional<T> contains a value, it means that an object of type T, referred to as the optional
object’s contained value, is allocated within the storage of the optional object. Implementations are not
permitted to use additional storage, such as dynamic memory, to allocate its contained value. The contained
value shall be allocated in a region of the optional<T> storage suitably aligned for the type T. When an
object of type optional<T> is contextually converted to bool, the conversion returns true if the object
contains a value; otherwise the conversion returns false.
2
Member val is provided for exposition only. When an optional<T> object contains a value, val points to
the contained value.
3
T shall be an object type and shall satisfy the requirements of Destructible (Table 27).
23.6.3.1
Constructors
[optional.ctor]
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
1
Postconditions: *this does not contain a value.
2
Remarks: No contained value is initialized. For every object type T these constructors shall be constexpr
constructors (10.1.5).
constexpr optional(const optional& rhs);
3
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object
of type T with the expression *rhs.
4
Postconditions: bool(rhs) == bool(*this).
5
Throws: Any exception thrown by the selected constructor of T.
6
Remarks: This constructor shall be defined as deleted unless is_copy_constructible_v<T> is true. If
is_trivially_copy_constructible_v<T> is true, this constructor shall be a constexpr constructor.
constexpr optional(optional&& rhs) noexcept(see below );
7
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object
of type T with the expression std::move(*rhs). bool(rhs) is unchanged.
8
Postconditions: bool(rhs) == bool(*this).
9
Throws: Any exception thrown by the selected constructor of T.
10
Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible_v<T>.
This constructor shall not participate in overload resolution unless is_move_constructible_v<T> is
true. If is_trivially_move_constructible_v<T> is true, this constructor shall be a constexpr
constructor.
template<class... Args> constexpr explicit optional(in_place_t, Args&&... args);
11
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the
arguments std::forward<Args>(args)
12
Postconditions: *this contains a value.
13
Throws: Any exception thrown by the selected constructor of T.
14
Remarks: If T’s constructor selected for the initialization is a constexpr constructor, this constructor
shall be a constexpr constructor. This constructor shall not participate in overload resolution unless
is_constructible_v<T, Args...> is true.
template<class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
15
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the
arguments il, std::forward<Args>(args)
16
Postconditions: *this contains a value.
17
Throws: Any exception thrown by the selected constructor of T.
§ 23.6.3.1
508
18
Remarks: This constructor shall not participate in overload resolution unless is_constructible_v<T,
initializer_list<U>&, Args&&...> is true. If T’s constructor selected for the initialization is a
constexpr constructor, this constructor shall be a constexpr constructor.
19
[Note: The following constructors are conditionally specified as explicit. This is typically implemented by
declaring two such constructors, of which at most one participates in overload resolution.
— end note ]
template<class U = T> EXPLICIT constexpr optional(U&& v);
20
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the
expression std::forward<U>(v).
21
Postconditions: *this contains a value.
22
Throws: Any exception thrown by the selected constructor of T.
23
Remarks: If T’s selected constructor is a constexpr constructor, this constructor shall be a constexpr con-
structor. This constructor shall not participate in overload resolution unless is_constructible_v<T,
U&&> is true, is_same_v<remove_cvref_t<U>, in_place_t> is false, and is_same_v<remove_-
cvref_t<U>, optional> is false. The constructor is explicit if and only if is_convertible_v<U&&,
T> is false.
template<class U> EXPLICIT optional(const optional<U>& rhs);
24
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object
of type T with the expression *rhs.
25
Postconditions: bool(rhs) == bool(*this).
26
Throws: Any exception thrown by the selected constructor of T.
27
Remarks: This constructor shall not participate in overload resolution unless
(27.1)
—
is_constructible_v<T, const U&> is true,
(27.2)
—
is_constructible_v<T, optional<U>&> is false,
(27.3)
—
is_constructible_v<T, optional<U>&&> is false,
(27.4)
—
is_constructible_v<T, const optional<U>&> is false,
(27.5)
—
is_constructible_v<T, const optional<U>&&> is false,
(27.6)
—
is_convertible_v<optional<U>&, T> is false,
(27.7)
—
is_convertible_v<optional<U>&&, T> is false,
(27.8)
—
is_convertible_v<const optional<U>&, T> is false, and
(27.9)
—
is_convertible_v<const optional<U>&&, T> is false.
The constructor is explicit if and only if is_convertible_v<const U&, T> is false.
template<class U> EXPLICIT optional(optional<U>&& rhs);
28
Effects: If rhs contains a value, initializes the contained value as if direct-non-list-initializing an object
of type T with the expression std::move(*rhs). bool(rhs) is unchanged.
29
Postconditions: bool(rhs) == bool(*this).
30
Throws: Any exception thrown by the selected constructor of T.
31
Remarks: This constructor shall not participate in overload resolution unless
(31.1)
—
is_constructible_v<T, U&&> is true,
(31.2)
—
is_constructible_v<T, optional<U>&> is false,
(31.3)
—
is_constructible_v<T, optional<U>&&> is false,
(31.4)
—
is_constructible_v<T, const optional<U>&> is false,
(31.5)
—
is_constructible_v<T, const optional<U>&&> is false,
(31.6)
—
is_convertible_v<optional<U>&, T> is false,
(31.7)
—
is_convertible_v<optional<U>&&, T> is false,
(31.8)
—
is_convertible_v<const optional<U>&, T> is false, and
§ 23.6.3.1
509
(31.9)
—
is_convertible_v<const optional<U>&&, T> is false.
The constructor is explicit if and only if is_convertible_v<U&&, T> is false.
23.6.3.2
Destructor
[optional.dtor]
~optional();
1
Effects: If is_trivially_destructible_v<T> != true and *this contains a value, calls
val->T::~T()
2
Remarks: If is_trivially_destructible_v<T> == true then this destructor shall be a trivial de-
structor.
23.6.3.3
Assignment
[optional.assign]
optional<T>& operator=(nullopt_t) noexcept;
1
Effects: If *this contains a value, calls val->T::~T() to destroy the contained value; otherwise no
effect.
2
Returns: *this.
3
Postconditions: *this does not contain a value.
optional<T>& operator=(const optional& rhs);
4
Effects: See Table 35.
Table 35 — optional::operator=(const optional&) effects
*this does not contain a
*this contains a value
value
initializes the contained value
rhs contains a
assigns *rhs to the contained
as if direct-non-list-initializing
value
value
an object of type T with *rhs
rhs does not
destroys the contained value
no effect
contain a value
by calling val->T::~T()
5
Returns: *this.
6
Postconditions: bool(rhs) == bool(*this).
7
Remarks: If any exception is thrown, the result of the expression bool(*this) remains unchanged. If an
exception is thrown during the call to T’s copy constructor, no effect. If an exception is thrown during the
call to T’s copy assignment, the state of its contained value is as defined by the exception safety guarantee
of T’s copy assignment. This operator shall be defined as deleted unless is_copy_constructible_v<T>
is true and is_copy_assignable_v<T> is true.
optional<T>& operator=(optional&& rhs) noexcept(see below );
8
Effects: See Table 36. The result of the expression bool(rhs) remains unchanged.
Table 36 — optional::operator=(optional&&) effects
*this does not contain a
*this contains a value
value
initializes the contained value
rhs contains a
assigns std::move(*rhs) to
as if direct-non-list-initializing
value
the contained value
an object of type T with
std::move(*rhs)
rhs does not
destroys the contained value
no effect
contain a value
by calling val->T::~T()
9
Returns: *this.
§ 23.6.3.3
510
10
Postconditions: bool(rhs) == bool(*this).
11
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>
12
If any exception is thrown, the result of the expression bool(*this) remains unchanged. If an
exception is thrown during the call to T’s move constructor, the state of *rhs.val is determined
by the exception safety guarantee of T’s move constructor. If an exception is thrown during the
call to T’s move assignment, the state of *val and *rhs.val is determined by the exception safety
guarantee of T’s move assignment. This operator shall not participate in overload resolution unless
is_move_constructible_v<T> is true and is_move_assignable_v<T> is true.
template<class U = T> optional<T>& operator=(U&& v);
13
Effects: If *this contains a value, assigns std::forward<U>(v) to the contained value; otherwise
initializes the contained value as if direct-non-list-initializing object of type T with std::forward<U>(v).
14
Returns: *this.
15
Postconditions: *this contains a value.
16
Remarks: If any exception is thrown, the result of the expression bool(*this) remains unchanged. If
an exception is thrown during the call to T’s constructor, the state of v is determined by the exception
safety guarantee of T’s constructor. If an exception is thrown during the call to T’s assignment, the state
of *val and v is determined by the exception safety guarantee of T’s assignment. This function shall
not participate in overload resolution unless is_same_v<remove_cvref_t<U>, optional> is false,
conjunction_v<is_scalar<T>, is_same<T, decay_t<U>>> is false, is_constructible_v<T, U>
is true, and is_assignable_v<T&, U> is true.
template<class U> optional<T>& operator=(const optional<U>& rhs);
17
Effects: See Table 37.
Table 37 — optional::operator=(const optional<U>&) effects
*this does not contain a
*this contains a value
value
initializes the contained value
rhs contains a
assigns *rhs to the contained
as if direct-non-list-initializing
value
value
an object of type T with *rhs
rhs does not
destroys the contained value
no effect
contain a value
by calling val->T::~T()
18
Returns: *this.
19
Postconditions: bool(rhs) == bool(*this).
20
Remarks: If any exception is thrown, the result of the expression bool(*this) remains unchanged.
If an exception is thrown during the call to T’s constructor, the state of *rhs.val is determined by
the exception safety guarantee of T’s constructor. If an exception is thrown during the call to T’s
assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T’s
assignment. This function shall not participate in overload resolution unless
(20.1)
—
is_constructible_v<T, const U&> is true,
(20.2)
—
is_assignable_v<T&, const U&> is true,
(20.3)
—
is_constructible_v<T, optional<U>&> is false,
(20.4)
—
is_constructible_v<T, optional<U>&&> is false,
(20.5)
—
is_constructible_v<T, const optional<U>&> is false,
(20.6)
—
is_constructible_v<T, const optional<U>&&> is false,
(20.7)
—
is_convertible_v<optional<U>&, T> is false,
(20.8)
—
is_convertible_v<optional<U>&&, T> is false,
(20.9)
—
is_convertible_v<const optional<U>&, T> is false,
§
23.6.3.3
511
(20.10)
—
is_convertible_v<const optional<U>&&, T> is false,
(20.11)
—
is_assignable_v<T&, optional<U>&> is false,
(20.12)
—
is_assignable_v<T&, optional<U>&&> is false,
(20.13)
—
is_assignable_v<T&, const optional<U>&> is false, and
(20.14)
—
is_assignable_v<T&, const optional<U>&&> is false.
template<class U> optional<T>& operator=(optional<U>&& rhs);
21
Effects: See Table 38. The result of the expression bool(rhs) remains unchanged.
Table 38 — optional::operator=(optional<U>&&) effects
*this does not contain a
*this contains a value
value
initializes the contained value
rhs contains a
assigns std::move(*rhs) to
as if direct-non-list-initializing
value
the contained value
an object of type T with
std::move(*rhs)
rhs does not
destroys the contained value
no effect
contain a value
by calling val->T::~T()
22
Returns: *this.
23
Postconditions: bool(rhs) == bool(*this).
24
Remarks: If any exception is thrown, the result of the expression bool(*this) remains unchanged.
If an exception is thrown during the call to T’s constructor, the state of *rhs.val is determined by
the exception safety guarantee of T’s constructor. If an exception is thrown during the call to T’s
assignment, the state of *val and *rhs.val is determined by the exception safety guarantee of T’s
assignment. This function shall not participate in overload resolution unless
(24.1)
—
is_constructible_v<T, U> is true,
(24.2)
—
is_assignable_v<T&, U> is true,
(24.3)
—
is_constructible_v<T, optional<U>&> is false,
(24.4)
—
is_constructible_v<T, optional<U>&&> is false,
(24.5)
—
is_constructible_v<T, const optional<U>&> is false,
(24.6)
—
is_constructible_v<T, const optional<U>&&> is false,
(24.7)
—
is_convertible_v<optional<U>&, T> is false,
(24.8)
—
is_convertible_v<optional<U>&&, T> is false,
(24.9)
—
is_convertible_v<const optional<U>&, T> is false,
(24.10)
—
is_convertible_v<const optional<U>&&, T> is false,
(24.11)
—
is_assignable_v<T&, optional<U>&> is false,
(24.12)
—
is_assignable_v<T&, optional<U>&&> is false,
(24.13)
—
is_assignable_v<T&, const optional<U>&> is false, and
(24.14)
—
is_assignable_v<T&, const optional<U>&&> is false.
template<class... Args> T& emplace(Args&&... args);
25
Requires: is_constructible_v<T, Args&&...> is true.
26
Effects: Calls *this = nullopt. Then initializes the contained value as if direct-non-list-initializing
an object of type T with the arguments std::forward<Args>(args)
27
Postconditions: *this contains a value.
28
Returns: A reference to the new contained value.
29
Throws: Any exception thrown by the selected constructor of T.
§ 23.6.3.3
512
30
Remarks: If an exception is thrown during the call to T’s constructor, *this does not contain a value,
and the previous *val (if any) has been destroyed.
template<class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
31
Effects: Calls *this = nullopt. Then initializes the contained value as if direct-non-list-initializing
an object of type T with the arguments il, std::forward<Args>(args)
32
Postconditions: *this contains a value.
33
Returns: A reference to the new contained value.
34
Throws: Any exception thrown by the selected constructor of T.
35
Remarks: If an exception is thrown during the call to T’s constructor, *this does not contain a value,
and the previous *val (if any) has been destroyed. This function shall not participate in overload
resolution unless is_constructible_v<T, initializer_list<U>&, Args&&...> is true.
23.6.3.4
Swap
[optional.swap]
void
swap(optional& rhs) noexcept(see below );
1
Requires: Lvalues of type T shall be swappable and is_move_constructible_v<T> is true.
2
Effects: See Table 39.
Table 39 — optional::swap(optional&) effects
*this does not contain a
*this contains a value
value
initializes the contained value
of
*this as if direct-non-
list-initializing an object of
type T with the expres-
rhs contains a
calls swap(*(*this), *rhs)
sion std::move(*rhs), fol-
value
lowed by rhs.val->T::~T();
postcondition is that
*this
contains a value and rhs does
not contain a value
initializes
the contained
value of rhs as if direct-
non-list-initializing an object
of type T with the expres-
rhs does not
sion std::move(*(*this)),
no effect
contain a value
followed by val->T::~T();
postcondition is that
*this
does not contain a value and
rhs contains a value
3
Throws: Any exceptions thrown by the operations in the relevant part of Table 39.
4
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>
If any exception is thrown, the results of the expressions bool(*this) and bool(rhs) remain unchanged.
If an exception is thrown during the call to function swap, the state of *val and *rhs.val is determined
by the exception safety guarantee of swap for lvalues of T. If an exception is thrown during the call to
T’s move constructor, the state of *val and *rhs.val is determined by the exception safety guarantee
of T’s move constructor.
23.6.3.5
Observers
[optional.observe]
constexpr const T* operator->() const;
constexpr T* operator->();
1
Requires: *this contains a value.
§ 23.6.3.5
513
2
Returns: val.
3
Throws: Nothing.
4
Remarks: These functions shall be constexpr functions.
constexpr const T& operator*() const&;
constexpr T& operator*() &;
5
Requires: *this contains a value.
6
Returns: *val.
7
Throws: Nothing.
8
Remarks: These functions shall be constexpr functions.
constexpr T&& operator*() &&;
constexpr const T&& operator*() const&&;
9
Requires: *this contains a value.
10
Effects: Equivalent to: return std::move(*val);
constexpr explicit operator bool() const noexcept;
11
Returns: true if and only if *this contains a value.
12
Remarks: This function shall be a constexpr function.
constexpr bool has_value() const noexcept;
13
Returns: true if and only if *this contains a value.
14
Remarks: This function shall be a constexpr function.
constexpr const T& value() const&;
constexpr T& value() &;
15
Effects: Equivalent to:
return bool(*this) ? *val : throw bad_optional_access();
constexpr T&& value() &&;
constexpr const T&& value() const&&;
16
Effects: Equivalent to:
return bool(*this) ? std::move(*val) : throw bad_optional_access();
template<class U> constexpr T value_or(U&& v) const&;
17
Effects: Equivalent to:
return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
18
Remarks: If is_copy_constructible_v<T> && is_convertible_v<U&&,
T> is false, the program
is ill-formed.
template<class U> constexpr T value_or(U&& v) &&;
19
Effects: Equivalent to:
return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
20
Remarks: If is_move_constructible_v<T> && is_convertible_v<U&&, T> is false, the program
is ill-formed.
23.6.3.6
Modifiers
[optional.mod]
void reset() noexcept;
1
Effects: If *this contains a value, calls val->T::~T() to destroy the contained value; otherwise no
effect.
2
Postconditions: *this does not contain a value.
§ 23.6.3.6
514
23.6.4
No-value state indicator
[optional.nullopt]
struct nullopt_t{see below };
inline constexpr nullopt_t nullopt(unspecified );
1
The struct nullopt_t is an empty structure type used as a unique type to indicate the state of not containing
a value for optional objects. In particular, optional<T> has a constructor with nullopt_t as a single
argument; this indicates that an optional object not containing a value shall be constructed.
2
Type nullopt_t shall not have a default constructor or an initializer-list constructor, and shall not be an
aggregate.
23.6.5
Class bad_optional_access
[optional.bad.access]
class bad_optional_access : public exception {
public:
bad_optional_access();
};
1
The class bad_optional_access defines the type of objects thrown as exceptions to report the situation
where an attempt is made to access the value of an optional object that does not contain a value.
bad_optional_access();
2
Effects: Constructs an object of class bad_optional_access.
3
Postconditions: what() returns an implementation-defined ntbs.
23.6.6
Relational operators
[optional.relops]
template<class T, class U> constexpr bool operator==(const optional<T>& x, const optional<U>& y);
1
Requires: The expression *x == *y shall be well-formed and its result shall be convertible to bool.
[ Note: T need not be EqualityComparable.
— end note ]
2
Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true; otherwise *x == *y.
3
Remarks: Specializations of this function template for which *x == *y is a core constant expression
shall be constexpr functions.
template<class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<U>& y);
4
Requires: The expression *x != *y shall be well-formed and its result shall be convertible to bool.
5
Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false; otherwise *x != *y.
6
Remarks: Specializations of this function template for which *x != *y is a core constant expression
shall be constexpr functions.
template<class T, class U> constexpr bool operator<(const optional<T>& x, const optional<U>& y);
7
Requires: *x < *y shall be well-formed and its result shall be convertible to bool.
8
Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y.
9
Remarks: Specializations of this function template for which *x < *y is a core constant expression
shall be constexpr functions.
template<class T, class U> constexpr bool operator>(const optional<T>& x, const optional<U>& y);
10
Requires: The expression *x > *y shall be well-formed and its result shall be convertible to bool.
11
Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y.
12
Remarks: Specializations of this function template for which *x > *y is a core constant expression
shall be constexpr functions.
template<class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<U>& y);
13
Requires: The expression *x <= *y shall be well-formed and its result shall be convertible to bool.
14
Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y.
15
Remarks: Specializations of this function template for which *x <= *y is a core constant expression
shall be constexpr functions.
§ 23.6.6
515
template<class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<U>& y);
16
Requires: The expression *x >= *y shall be well-formed and its result shall be convertible to bool.
17
Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y.
18
Remarks: Specializations of this function template for which *x >= *y is a core constant expression
shall be constexpr functions.
23.6.7
Comparison with nullopt
[optional.nullops]
template<class T> constexpr
bool
operator==(const optional<T>& x, nullopt_t) noexcept;
template<class T> constexpr
bool
operator==(nullopt_t, const optional<T>& x) noexcept;
1
Returns: !x.
template<class T> constexpr
bool
operator!=(const optional<T>& x, nullopt_t) noexcept;
template<class T> constexpr
bool
operator!=(nullopt_t, const optional<T>& x) noexcept;
2
Returns: bool(x).
template<class T> constexpr
bool
operator<(const optional<T>& x, nullopt_t) noexcept;
3
Returns: false.
template<class T> constexpr
bool
operator<(nullopt_t, const optional<T>& x) noexcept;
4
Returns: bool(x).
template<class T> constexpr
bool
operator<=(const optional<T>& x, nullopt_t) noexcept;
5
Returns: !x.
template<class T> constexpr
bool
operator<=(nullopt_t, const optional<T>& x) noexcept;
6
Returns: true.
template<class T> constexpr
bool
operator>(const optional<T>& x, nullopt_t) noexcept;
7
Returns: bool(x).
template<class T> constexpr
bool
operator>(nullopt_t, const optional<T>& x) noexcept;
8
Returns: false.
template<class T> constexpr
bool
operator>=(const optional<T>& x, nullopt_t) noexcept;
9
Returns: true.
template<class T> constexpr
bool
operator>=(nullopt_t, const optional<T>& x) noexcept;
10
Returns: !x.
23.6.8
Comparison with T
[optional.comp_with_t]
template<class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);
1
Requires: The expression *x == v shall be well-formed and its result shall be convertible to bool.
[ Note: T need not be EqualityComparable.
— end note ]
2
Effects: Equivalent to: return bool(x) ? *x == v : false;
template<class T, class U> constexpr bool operator==(const T& v, const optional<U>& x);
3
Requires: The expression v == *x shall be well-formed and its result shall be convertible to bool.
4
Effects: Equivalent to: return bool(x) ? v == *x : false;
template<class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);
5
Requires: The expression *x != v shall be well-formed and its result shall be convertible to bool.
6
Effects: Equivalent to: return bool(x) ? *x != v : true;
template<class T, class U> constexpr bool operator!=(const T& v, const optional<U>& x);
7
Requires: The expression v != *x shall be well-formed and its result shall be convertible to bool.
§ 23.6.8
516
8
Effects: Equivalent to: return bool(x) ? v != *x : true;
template<class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);
9
Requires: The expression *x < v shall be well-formed and its result shall be convertible to bool.
10
Effects: Equivalent to: return bool(x) ? *x < v : true;
template<class T, class U> constexpr bool operator<(const T& v, const optional<U>& x);
11
Requires: The expression v < *x shall be well-formed and its result shall be convertible to bool.
12
Effects: Equivalent to: return bool(x) ? v < *x : false;
template<class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);
13
Requires: The expression *x <= v shall be well-formed and its result shall be convertible to bool.
14
Effects: Equivalent to: return bool(x) ? *x <= v : true;
template<class T, class U> constexpr bool operator<=(const T& v, const optional<U>& x);
15
Requires: The expression v <= *x shall be well-formed and its result shall be convertible to bool.
16
Effects: Equivalent to: return bool(x) ? v <= *x : false;
template<class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);
17
Requires: The expression *x > v shall be well-formed and its result shall be convertible to bool.
18
Effects: Equivalent to: return bool(x) ? *x > v : false;
template<class T, class U> constexpr bool operator>(const T& v, const optional<U>& x);
19
Requires: The expression v > *x shall be well-formed and its result shall be convertible to bool.
20
Effects: Equivalent to: return bool(x) ? v > *x : true;
template<class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);
21
Requires: The expression *x >= v shall be well-formed and its result shall be convertible to bool.
22
Effects: Equivalent to: return bool(x) ? *x >= v : false;
template<class T, class U> constexpr bool operator>=(const T& v, const optional<U>& x);
23
Requires: The expression v >= *x shall be well-formed and its result shall be convertible to bool.
24
Effects: Equivalent to: return bool(x) ? v >= *x : true;
23.6.9
Specialized algorithms
[optional.specalg]
template<class T> void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));
1
Effects: Calls x.swap(y).
2
Remarks: This function shall not participate in overload resolution unless is_move_constructible_-
v<T> is true and is_swappable_v<T> is true.
template<class T> constexpr optional<decay_t<T>> make_optional(T&& v);
3
Returns: optional<decay_t<T>>(std::forward<T>(v)).
template<class T, class...Args>
constexpr optional<T> make_optional(Args&&... args);
4
Effects: Equivalent to: return optional<T>(in_place, std::forward<Args>(args)...);
template<class T, class U, class... Args>
constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
5
Effects: Equivalent to: return optional<T>(in_place, il, std::forward<Args>(args)...);
23.6.10
Hash support
[optional.hash]
template<class T> struct hash<optional<T>>;
1
The specialization hash<optional<T>> is enabled (23.14.15) if and only if hash<remove_const_-
§ 23.6.10
517
t<T>> is enabled. When enabled, for an object o of type optional<T>, if bool(o) == true, then
hash<optional<T>>()(o) shall evaluate to the same value as hash<remove_const_t<T>>()(*o); oth-
erwise it evaluates to an unspecified value. The member functions are not guaranteed to be noexcept.
23.7
Variants
[variant]
23.7.1
In general
[variant.general]
1
A variant object holds and manages the lifetime of a value. If the variant holds a value, that value’s type has
to be one of the template argument types given to variant. These template arguments are called alternatives.
23.7.2
Header <variant> synopsis
[variant.syn]
namespace std {
// 23.7.3, class template variant
template<class... Types>
class variant;
// 23.7.4, variant helper classes
template<class T> struct variant_size;
// not defined
template<class T> struct variant_size<const T>;
template<class T> struct variant_size<volatile T>;
template<class T> struct variant_size<const volatile T>;
template<class T>
inline constexpr size_t variant_size_v = variant_size<T>::value;
template<class... Types>
struct variant_size<variant<Types...>>;
template<size_t I, class T> struct variant_alternative;
// not defined
template<size_t I, class T> struct variant_alternative<I, const T>;
template<size_t I, class T> struct variant_alternative<I, volatile T>;
template<size_t I, class T> struct variant_alternative<I, const volatile T>;
template<size_t I, class T>
using variant_alternative_t = 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;
// 23.7.5, value access
template<class T, class... Types>
constexpr bool holds_alternative(const variant<Types...>&) noexcept;
template<size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>&);
template<size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&);
template<size_t I, class... Types>
constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&);
template<size_t I, class... Types>
constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&);
template<class T, class... Types>
constexpr T& get(variant<Types...>&);
template<class T, class... Types>
constexpr T&& get(variant<Types...>&&);
template<class T, class... Types>
constexpr const T& get(const variant<Types...>&);
template<class T, class... Types>
constexpr const T&& get(const variant<Types...>&&);
§ 23.7.2
518
template<size_t I, class... Types>
constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
get_if(variant<Types...>*) noexcept;
template<size_t I, class... Types>
constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
get_if(const variant<Types...>*) noexcept;
template<class T, class... Types>
constexpr add_pointer_t<T>
get_if(variant<Types...>*) noexcept;
template<class T, class... Types>
constexpr add_pointer_t<const T>
get_if(const variant<Types...>*) noexcept;
// 23.7.6, relational operators
template<class... Types>
constexpr bool operator==(const variant<Types...>&, const variant<Types...>&);
template<class... Types>
constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&);
template<class... Types>
constexpr bool operator<(const variant<Types...>&, const variant<Types...>&);
template<class... Types>
constexpr bool operator>(const variant<Types...>&, const variant<Types...>&);
template<class... Types>
constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&);
template<class... Types>
constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
// 23.7.7, visitation
template<class Visitor, class... Variants>
constexpr see below visit(Visitor&&, Variants&&...);
// 23.7.8, class monostate
struct monostate;
// 23.7.9, monostate relational operators
constexpr bool operator<(monostate, monostate) noexcept;
constexpr bool operator>(monostate, monostate) noexcept;
constexpr bool operator<=(monostate, monostate) noexcept;
constexpr bool operator>=(monostate, monostate) noexcept;
constexpr bool operator==(monostate, monostate) noexcept;
constexpr bool operator!=(monostate, monostate) noexcept;
// 23.7.10, specialized algorithms
template<class... Types>
void swap(variant<Types...>&, variant<Types...>&) noexcept(see
below );
// 23.7.11, class bad_variant_access
class bad_variant_access;
// 23.7.12, hash support
template<class T> struct hash;
template<class... Types> struct hash<variant<Types...>>;
template<> struct hash<monostate>;
}
23.7.3
Class template variant
[variant.variant]
namespace std {
template<class... Types>
class variant {
public:
// 23.7.3.1, constructors
constexpr variant() noexcept(see below );
§ 23.7.3
519
variant(const variant&);
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&&...);
// 23.7.3.2, destructor
~variant();
// 23.7.3.3, assignment
variant& operator=(const variant&);
variant& operator=(variant&&) noexcept(see below );
template<class T> variant& operator=(T&&) noexcept(see below );
// 23.7.3.4, modifiers
template<class T, class... Args>
T& emplace(Args&&...);
template<class T, class U, class... Args>
T& emplace(initializer_list<U>, Args&&...);
template<size_t I, class... Args>
variant_alternative_t<I, variant<Types...>>& emplace(Args&&...);
template<size_t I, class U, class... Args>
variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U>, Args&&...);
// 23.7.3.5, value status
constexpr bool valueless_by_exception() const noexcept;
constexpr size_t index() const noexcept;
// 23.7.3.6, swap
void swap(variant&) noexcept(see below );
};
}
1
Any instance of variant at any given time either holds a value of one of its alternative types, or it 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 allocated within the storage of the variant object.
Implementations are not permitted to use additional storage, such as dynamic memory, to allocate the
contained value. The contained value shall be allocated in a region of the variant storage suitably aligned
for all types in Types
It is implementation-defined whether over-aligned types are supported.
2
All types in Types... shall be (possibly cv-qualified) object types that are not arrays.
3
A program that instantiates the definition of variant with no template arguments is ill-formed.
23.7.3.1
Constructors
[variant.ctor]
1
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 );
2
Effects: Constructs a variant holding a value-initialized value of type T0.
3
Postconditions: valueless_by_exception() is false and index() is 0.
4
Throws: Any exception thrown by the value-initialization of T0.
§ 23.7.3.1
520
5
Remarks: This function shall be constexpr if and only if the value-initialization of the alternative
type T0 would satisfy the requirements for a constexpr function. The expression inside noexcept
is equivalent to is_nothrow_default_constructible_v<T0>. This function shall not participate in
overload resolution unless is_default_constructible_v<T0> is true. [ Note: See also class monostate.
— end note ]
variant(const variant& w);
6
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.
7
Throws: Any exception thrown by direct-initializing any Ti for all i.
8
Remarks: This constructor shall be defined as deleted unless is_copy_constructible_v<Ti> is true
for all i.
variant(variant&& w) noexcept(see below );
9
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.
10
Throws: Any exception thrown by move-constructing any Ti for all i.
11
Remarks: The expression inside noexcept is equivalent to the logical AND of is_nothrow_move_-
constructible_v<Ti> for all i. This function shall not participate in overload resolution unless
is_move_constructible_v<Ti> is true for all i.
template<class T> constexpr variant(T&& t) noexcept(see below );
12
Let Tj be a type that is determined as follows: build an imaginary function FUN(Ti) for each alternative
type Ti. 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.
13
Effects: Initializes *this to hold the alternative type Tj and direct-initializes the contained value as if
direct-non-list-initializing it with std::forward<T>(t).
14
Postconditions: holds_alternative<Tj >(*this) is true.
15
Throws: Any exception thrown by the initialization of the selected alternative Tj .
16
Remarks: This function shall not participate in overload resolution unless
(16.1)
—
sizeof...(Types) is nonzero,
(16.2)
—
is_same_v<remove_cvref_t<T>, variant> is false,
(16.3)
—
remove_cvref_t<T> is neither a specialization of in_place_type_t nor a specialization of in_-
place_index_t,
(16.4)
—
is_constructible_v<Tj , T> is true, and
(16.5)
—
the expression FUN(std::forward<T>(t)) (with FUN being the above-mentioned set of imaginary
functions) is well-formed.
17
[ Note:
variant<string, string> v("abc");
is ill-formed, as both alternative types have an equally viable constructor for the argument.
— end
note ]
18
The expression inside noexcept is equivalent to is_nothrow_constructible_v<Tj , T>. If Tj ’s selected
constructor is a constexpr constructor, this constructor shall be a constexpr constructor.
template<class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
19
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the
arguments std::forward<Args>(args)
20
Postconditions: holds_alternative<T>(*this) is true.
21
Throws: Any exception thrown by calling the selected constructor of T.
§ 23.7.3.1
521
22
Remarks: This function shall not participate in overload resolution unless there is exactly one occurrence
of T in Types... and is_constructible_v<T, Args...> is true. If T’s selected constructor is a
constexpr constructor, this constructor shall be a constexpr constructor.
template<class T, class U, class... Args>
constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
23
Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the
arguments il, std::forward<Args>(args)
24
Postconditions: holds_alternative<T>(*this) is true.
25
Throws: Any exception thrown by calling the selected constructor of T.
26
Remarks: This function shall not participate in overload resolution unless there is exactly one occurrence
of T in Types... and is_constructible_v<T, initializer_list<U>&, Args...> is true. If T’s
selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.
template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
27
Effects: Initializes the contained value as if direct-non-list-initializing an object of type TI with the
arguments std::forward<Args>(args)
28
Postconditions: index() is I.
29
Throws: Any exception thrown by calling the selected constructor of TI .
30
Remarks: This function shall not participate in overload resolution unless
(30.1)
—
I is less than sizeof...(Types) and
(30.2)
—
is_constructible_v<TI , Args...> is true.
If TI ’s selected constructor is a constexpr constructor, this constructor shall be 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);
31
Effects: Initializes the contained value as if direct-non-list-initializing an object of type TI with the
arguments il, std::forward<Args>(args)
32
Postconditions: index() is I.
33
Remarks: This function shall not participate in overload resolution unless
(33.1)
—
I is less than sizeof...(Types) and
(33.2)
—
is_constructible_v<TI , initializer_list<U>&, Args...> is true.
If TI ’s selected constructor is a constexpr constructor, this constructor shall be a constexpr constructor.
23.7.3.2
Destructor
[variant.dtor]
~variant();
1
Effects: If valueless_by_exception() is false, destroys the currently contained value.
2
Remarks: If is_trivially_destructible_v<Ti> == true for all Ti then this destructor shall be a
trivial destructor.
23.7.3.3
Assignment
[variant.assign]
variant& operator=(const variant& rhs);
1
Let j be rhs.index().
2
Effects:
(2.1)
—
If neither *this nor rhs holds a value, there is no effect.
(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.
(2.3)
—
Otherwise, if index() == j, assigns the value contained in rhs to the value contained in *this.
(2.4)
—
Otherwise, if either is_nothrow_copy_constructible_v<Tj > is true or is_nothrow_move_con-
structible_v<Tj > is false, equivalent to emplace<j>(get<j>(rhs)).
§ 23.7.3.3
522
(2.5)
—
Otherwise, equivalent to operator=(variant(rhs)).
3
Returns: *this.
4
Postconditions: index() == rhs.index().
5
Remarks: This operator shall be defined as deleted unless is_copy_constructible_v<Ti> && is_-
copy_assignable_v<Ti> is true for all i.
variant& operator=(variant&& rhs) noexcept(see below );
6
Let j be rhs.index().
7
Effects:
(7.1)
—
If neither *this nor rhs holds a value, there is no effect.
(7.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.
(7.3)
—
Otherwise, if index() == j, assigns get<j>(std::move(rhs)) to the value contained in *this.
(7.4)
—
Otherwise, equivalent to emplace<j>(get<j>(std::move(rhs))).
8
Returns: *this.
9
Remarks: This function shall not participate in overload resolution unless is_move_constructible_-
v<Ti> && is_move_assignable_v<Ti> is true for all i. The expression inside noexcept is equivalent
to: is_nothrow_move_constructible_v<Ti> && is_nothrow_move_assignable_v<Ti> for all i.
(9.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.
(9.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.
template<class T> variant& operator=(T&& t) noexcept(see below );
10
Let Tj be a type that is determined as follows: build an imaginary function FUN(Ti) for each alternative
type Ti. 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.
11
Effects:
(11.1)
—
If *this holds a Tj , assigns std::forward<T>(t) to the value contained in *this.
(11.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)).
(11.3)
—
Otherwise, equivalent to operator=(variant(std::forward<T>(t))).
12
Postconditions: holds_alternative<Tj >(*this) is true, with Tj selected by the imaginary function
overload resolution described above.
13
Returns: *this.
14
Remarks: This function shall not participate in overload resolution unless
(14.1)
—
is_same_v<remove_cvref_t<T>, variant> is false,
(14.2)
—
is_assignable_v<Tj &, T> && is_constructible_v<Tj , T> is true, and
(14.3)
—
the expression FUN(std::forward<T>(t)) (with FUN being the above-mentioned set of imaginary
functions) is well-formed.
15
[ Note:
variant<string, string> v;
v = "abc";
is ill-formed, as both alternative types have an equally viable constructor for the argument.
— end
note ]
16
The expression inside noexcept is equivalent to:
is_nothrow_assignable_v<Tj &, T> && is_nothrow_constructible_v<Tj , T>
§ 23.7.3.3
523
(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 and t are as defined by the exception safety guarantee
of the assignment expression; valueless_by_exception() will be false.
(16.2)
—
If an exception is thrown during the initialization of the contained value, the variant object might
not hold a value.
23.7.3.4
Modifiers
[variant.mod]
template<class T, class... Args> T& emplace(Args&&... args);
1
Let I be the zero-based index of T in Types
2
Effects: Equivalent to: return emplace<I>(std::forward<Args>(args)...);
3
Remarks: This function shall not participate in overload resolution unless is_constructible_v<T,
Args...> is true, and T occurs exactly once in Types
template<class T, class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
4
Let I be the zero-based index of T in Types
5
Effects: Equivalent to: return emplace<I>(il, std::forward<Args>(args)...);
6
Remarks: This function shall not participate in overload resolution unless is_constructible_v<T,
initializer_list<U>&, Args...> is true, and T occurs exactly once in Types
template<size_t I, class... Args>
variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
7
Requires: I < sizeof...(Types).
8
Effects: Destroys the currently contained value if valueless_by_exception() is false. Then ini-
tializes the contained value as if direct-non-list-initializing a value of type TI with the arguments
std::forward<Args>(args)
9
Postconditions: index() is I.
10
Returns: A reference to the new contained value.
11
Throws: Any exception thrown during the initialization of the contained value.
12
Remarks: This function shall not participate in overload resolution unless is_constructible_v<TI ,
Args...> is true. If an exception is thrown during the initialization of the contained value, the variant
might not hold a value.
template<size_t I, class U, class... Args>
variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args);
13
Requires: I < sizeof...(Types).
14
Effects: Destroys the currently contained value if valueless_by_exception() is false. Then ini-
tializes the contained value as if direct-non-list-initializing a value of type TI with the arguments il,
std::forward<Args>(args)
15
Postconditions: index() is I.
16
Returns: A reference to the new contained value.
17
Throws: Any exception thrown during the initialization of the contained value.
18
Remarks: This function shall not participate in overload resolution unless is_constructible_v<TI ,
initializer_list<U>&, Args...> is true. If an exception is thrown during the initialization of the
contained value, the variant might not hold a value.
23.7.3.5
Value status
[variant.status]
constexpr bool valueless_by_exception() const noexcept;
1
Effects: Returns false if and only if the variant holds a value.
2
[ Note: A variant might not hold a 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
§ 23.7.3.5
524
struct S { operator int() { throw 42; }};
variant<float, int> v{12.f};
v.emplace<1>(S());
— end note ]
constexpr size_t index() const noexcept;
3
Effects: If valueless_by_exception() is true, returns variant_npos. Otherwise, returns the zero-
based index of the alternative of the contained value.
23.7.3.6
Swap
[variant.swap]
void swap(variant& rhs) noexcept(see below );
1
Requires: Lvalues of type Ti shall be swappable (20.5.3.2) and is_move_constructible_v<Ti> shall
be true for all i.
2
Effects:
(2.1)
—
If valueless_by_exception() && rhs.valueless_by_exception() no effect.
(2.2)
—
Otherwise, if index() == rhs.index(), calls swap(get<i>(*this), get<i>(rhs)) where i is
index().
(2.3)
—
Otherwise, exchanges values of rhs and *this.
3
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().
4
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 expression inside noexcept is equivalent to the
logical AND of is_nothrow_move_constructible_v<Ti> && is_nothrow_swappable_v<Ti> for all i.
23.7.4
variant helper classes
[variant.helper]
template<class T> struct variant_size;
1
Remarks: All specializations of variant_size shall meet the UnaryTypeTrait requirements (23.15.1)
with a base characteristic of integral_constant<size_t, N> for some N.
template<class T> class variant_size<const T>;
template<class T> class variant_size<volatile T>;
template<class T> class variant_size<const volatile T>;
2
Let VS denote variant_size<T> of the cv-unqualified type T. Then each of the three templates shall meet
the UnaryTypeTrait requirements (23.15.1) with a base characteristic of integral_constant<size_t,
VS::value>.
template<class... Types>
struct variant_size<variant<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class T> class variant_alternative<I, const T>;
template<size_t I, class T> class variant_alternative<I, volatile T>;
template<size_t I, class T> class variant_alternative<I, const volatile T>;
3
Let VA denote variant_alternative<I, T> of the cv-unqualified type T. Then each of the three
templates shall meet the TransformationTrait requirements (23.15.1) with a member typedef type
that names the following type:
(3.1)
—
for the first specialization, add_const_t<VA::type>,
(3.2)
—
for the second specialization, add_volatile_t<VA::type>, and
(3.3)
—
for the third specialization, add_cv_t<VA::type>.
§ 23.7.4
525
variant_alternative<I, variant<Types...>>::type
4
Requires: I < sizeof...(Types). The program is ill-formed if I is out of bounds.
5
Value: The type TI .
23.7.5
Value access
[variant.get]
template<class T, class... Types>
constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
1
Requires: The type T occurs exactly once in Types
Otherwise, the program is ill-formed.
2
Returns: true if index() is equal to the zero-based index of T in Types
template<size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v);
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);
3
Requires: I < sizeof...(Types). Otherwise the program is ill-formed.
4
Effects: If v.index() is I, returns a reference to the object stored in the variant. Otherwise, throws
an exception of type bad_variant_access.
template<class T, class... Types> constexpr T& get(variant<Types...>& v);
template<class T, class... Types> constexpr T&& get(variant<Types...>&& v);
template<class T, class... Types> constexpr const T& get(const variant<Types...>& v);
template<class T, class... Types> constexpr const T&& get(const variant<Types...>&& v);
5
Requires: The type T occurs exactly once in Types
Otherwise, the program is ill-formed.
6
Effects: If v holds a value of type T, returns a reference to that value. Otherwise, throws an exception
of type bad_variant_access.
template<size_t I, class... Types>
constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
get_if(variant<Types...>* v) noexcept;
template<size_t I, class... Types>
constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
get_if(const variant<Types...>* v) noexcept;
7
Requires: I < sizeof...(Types). Otherwise the program is ill-formed.
8
Returns: A pointer to the value stored in the variant, if v != nullptr and v->index() == I.
Otherwise, returns nullptr.
template<class T, class... Types>
constexpr add_pointer_t<T>
get_if(variant<Types...>* v) noexcept;
template<class T, class... Types>
constexpr add_pointer_t<const T>
get_if(const variant<Types...>* v) noexcept;
9
Requires: The type T occurs exactly once in Types
Otherwise, the program is ill-formed.
10
Effects: Equivalent to: return get_if<i>(v); with i being the zero-based index of T in Types
23.7.6
Relational operators
[variant.relops]
template<class... Types>
constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
1
Requires: get<i>(v) == get<i>(w) is a valid expression returning a type that is convertible to bool,
for all i.
2
Returns: If v.index() != w.index(), false; otherwise if v.valueless_by_exception(), true; oth-
erwise get<i>(v) == get<i>(w) with i being v.index().
§ 23.7.6
526
template<class... Types>
constexpr bool operator!=(const variant<Types...>& v, const variant<Types...>& w);
3
Requires: get<i>(v) != get<i>(w) is a valid expression returning a type that is convertible to bool,
for all i.
4
Returns: If v.index() != w.index(), true; otherwise if v.valueless_by_exception(), false; oth-
erwise get<i>(v) != get<i>(w) with i being v.index().
template<class... Types>
constexpr bool operator<(const variant<Types...>& v, const variant<Types...>& w);
5
Requires: get<i>(v) < get<i>(w) is a valid expression returning a type that is convertible to bool,
for all i.
6
Returns: If w.valueless_by_exception(), false; otherwise if v.valueless_by_exception(), true;
otherwise, if v.index() < w.index(), true; otherwise if v.index() > w.index(), false; otherwise
get<i>(v) < get<i>(w) with i being v.index().
template<class... Types>
constexpr bool operator>(const variant<Types...>& v, const variant<Types...>& w);
7
Requires: get<i>(v) > get<i>(w) is a valid expression returning a type that is convertible to bool,
for all i.
8
Returns: If v.valueless_by_exception(), false; otherwise if w.valueless_by_exception(), true;
otherwise, if v.index() > w.index(), true; otherwise if v.index() < w.index(), false; otherwise
get<i>(v) > get<i>(w) with i being v.index().
template<class... Types>
constexpr bool operator<=(const variant<Types...>& v, const variant<Types...>& w);
9
Requires: get<i>(v) <= get<i>(w) is a valid expression returning a type that is convertible to bool,
for all i.
10
Returns: If v.valueless_by_exception(), true; otherwise if w.valueless_by_exception(), false;
otherwise, if v.index() < w.index(), true; otherwise if v.index() > w.index(), false; otherwise
get<i>(v) <= get<i>(w) with i being v.index().
template<class... Types>
constexpr bool operator>=(const variant<Types...>& v, const variant<Types...>& w);
11
Requires: get<i>(v) >= get<i>(w) is a valid expression returning a type that is convertible to bool,
for all i.
12
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().
23.7.7
Visitation
[variant.visit]
template<class Visitor, class... Variants>
constexpr see below visit(Visitor&& vis, Variants&&... vars);
1
Requires: The expression in the Effects: element shall be a valid expression of the same type and value
category, for all combinations of alternative types of all variants. Otherwise, the program is ill-formed.
2
Effects: Let is... be vars.index()
Returns INVOKE(forward<Visitor>(vis), get<is>(
forward<Variants>(vars))...); (23.14.3).
3
Remarks: The return type is the common type of all possible INVOKE expressions of the Effects: element.
4
Throws: bad_variant_access if any variant in vars is valueless_by_exception().
5
Complexity: For sizeof...(Variants) <= 1, the invocation of the callable object is implemented in
constant time, i.e., it does not depend on sizeof...(Types). For sizeof...(Variants) > 1, the
invocation of the callable object has no complexity requirements.
§ 23.7.7
527
23.7.8
Class monostate
[variant.monostate]
struct monostate{};
1
The class monostate can serve as a first alternative type for a variant to make the variant type
default constructible.
23.7.9
monostate relational operators
[variant.monostate.relops]
constexpr bool operator<(monostate, monostate) noexcept { return false; }
constexpr bool operator>(monostate, monostate) noexcept { return false; }
constexpr bool operator<=(monostate, monostate) noexcept { return true; }
constexpr bool operator>=(monostate, monostate) noexcept { return true; }
constexpr bool operator==(monostate, monostate) noexcept { return true; }
constexpr bool operator!=(monostate, monostate) noexcept { return false; }
1
[ Note: monostate objects have only a single state; they thus always compare equal. — end note ]
23.7.10
Specialized algorithms
[variant.specalg]
template<class... Types>
void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below );
1
Effects: Equivalent to v.swap(w).
2
Remarks: This function shall not participate in overload resolution unless is_move_constructible_-
v<Ti> && is_swappable_v<Ti> is true for all i. The expression inside noexcept is equivalent to
noexcept(v.swap(w)).
23.7.11
Class bad_variant_access
[variant.bad.access]
class bad_variant_access : public exception {
public:
bad_variant_access() noexcept;
const char* what() const noexcept override;
};
1
Objects of type bad_variant_access are thrown to report invalid accesses to the value of a variant object.
bad_variant_access() noexcept;
2
Constructs a bad_variant_access object.
const char* what() const noexcept override;
3
Returns: An implementation-defined ntbs.
23.7.12
Hash support
[variant.hash]
template<class... Types> struct hash<variant<Types...>>;
1
The specialization hash<variant<Types...>> is enabled (23.14.15) if and only if every specialization
in hash<remove_const_t<Types>>... is enabled. The member functions are not guaranteed to be
noexcept.
template<> struct hash<monostate>;
2
The specialization is enabled (23.14.15).
23.8
Storage for any type
[any]
1
This subclause describes components that C++ programs may use to perform operations on objects of a
discriminated type.
2
[ Note: The discriminated type may contain values of different types but does not attempt conversion between
them, i.e., 5 is held strictly as an int and is not implicitly convertible either to "5" or to 5.0. This indifference
to interpretation but awareness of type effectively allows safe, generic containers of single values, with no
scope for surprises from ambiguous conversions.
— end note ]
§ 23.8
528
23.8.1
Header <any> synopsis
[any.synop]
namespace std {
// 23.8.2, class bad_any_cast
class bad_any_cast;
// 23.8.3, class any
class any;
// 23.8.4, non-member functions
void swap(any& x, any& y) noexcept;
template<class T, class... Args>
any make_any(Args&& ...args);
template<class T, class U, class... Args>
any make_any(initializer_list<U> il, Args&& ...args);
template<class T>
T any_cast(const any& operand);
template<class T>
T any_cast(any& operand);
template<class T>
T any_cast(any&& operand);
template<class T>
const T* any_cast(const any* operand) noexcept;
template<class T>
T* any_cast(any* operand) noexcept;
}
23.8.2
Class bad_any_cast
[any.bad_any_cast]
class bad_any_cast : public bad_cast {
public:
const char* what() const noexcept override;
};
1
Objects of type bad_any_cast are thrown by a failed any_cast (23.8.4).
const char* what() const noexcept override;
2
Returns: An implementation-defined ntbs.
3
Remarks: The message may be a null-terminated multibyte string (20.4.2.1.5.2), suitable for conversion
and display as a wstring (24.3, 25.4.1.4).
23.8.3
Class any
[any.class]
class any {
public:
// 23.8.3.1, construction and destruction
constexpr any() noexcept;
any(const any& other);
any(any&& other) noexcept;
template<class T> any(T&& value);
template<class T, class... Args>
explicit any(in_place_type_t<T>, Args&&...);
template<class T, class U, class... Args>
explicit any(in_place_type_t<T>, initializer_list<U>, Args&&...);
~any();
// 23.8.3.2, assignments
any& operator=(const any& rhs);
any& operator=(any&& rhs) noexcept;
§ 23.8.3
529
template<class T> any& operator=(T&& rhs);
// 23.8.3.3, modifiers
template<class T, class... Args>
decay_t<T>& emplace(Args&& ...);
template<class T, class U, class... Args>
decay_t<T>& emplace(initializer_list<U>, Args&&...);
void reset() noexcept;
void swap(any& rhs) noexcept;
// 23.8.3.4, observers
bool has_value() const noexcept;
const type_info& type() const noexcept;
};
1
An object of class any stores an instance of any type that satisfies the constructor requirements or it has no
value, and this is referred to as the state of the class any object. The stored instance is called the contained
value. Two states are equivalent if either they both have no value, or both have a value and the contained
values are equivalent.
2
The non-member any_cast functions provide type-safe access to the contained value.
3
Implementations should avoid the use of dynamically allocated memory for a small contained value. [ Example:
where the object constructed is holding only an int.
— end example ] Such small-object optimization shall
only be applied to types T for which is_nothrow_move_constructible_v<T> is true.
23.8.3.1
Construction and destruction
[any.cons]
constexpr any() noexcept;
1
Postconditions: has_value() is false.
any(const any& other);
2
Effects: If other.has_value() is false, constructs an object that has no value. Otherwise, equivalent
to any(in_place_type<T>, any_cast<const T&>(other)) where T is the type of the contained value.
3
Throws: Any exceptions arising from calling the selected constructor for the contained value.
any(any&& other) noexcept;
4
Effects: If other.has_value() is false, constructs an object that has no value. Otherwise, constructs
an object of type any that contains either the contained value of other, or contains an object of the
same type constructed from the contained value of other considering that contained value as an rvalue.
5
Postconditions: other is left in a valid but otherwise unspecified state.
template<class T>
any(T&& value);
6
Let VT be decay_t<T>.
7
Requires: VT shall satisfy the CopyConstructible requirements.
8
Effects: Constructs an object of type any that contains an object of type VT direct-initialized with
std::forward<T>(value).
9
Remarks: This constructor shall not participate in overload resolution unless VT is not the same type
as any, VT is not a specialization of in_place_type_t, and is_copy_constructible_v<VT> is true.
10
Throws: Any exception thrown by the selected constructor of VT.
template<class T, class... Args>
explicit any(in_place_type_t<T>, Args&&... args);
11
Let VT be decay_t<T>.
12
Requires: VT shall satisfy the CopyConstructible requirements.
13
Effects: Initializes the contained value as if direct-non-list-initializing an object of type VT with the
arguments std::forward<Args>(args)
14
Postconditions: *this contains a value of type VT.
§ 23.8.3.1
530
15
Throws: Any exception thrown by the selected constructor of VT.
16
Remarks: This constructor shall not participate in overload resolution unless is_copy_constructible_-
v<VT> is true and is_constructible_v<VT, Args...> is true.
template<class T, class U, class... Args>
explicit any(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
17
Let VT be decay_t<T>.
18
Requires: VT shall satisfy the CopyConstructible requirements.
19
Effects: Initializes the contained value as if direct-non-list-initializing an object of type VT with the
arguments il, std::forward<Args>(args)
20
Postconditions: *this contains a value.
21
Throws: Any exception thrown by the selected constructor of VT.
22
Remarks: This constructor shall not participate in overload resolution unless is_copy_constructible_-
v<VT> is true and is_constructible_v<VT, initializer_list<U>&, Args...> is true.
~any();
23
Effects: As if by reset().
23.8.3.2
Assignment
[any.assign]
any& operator=(const any& rhs);
1
Effects: As if by any(rhs).swap(*this). No effects if an exception is thrown.
2
Returns: *this.
3
Throws: Any exceptions arising from the copy constructor for the contained value.
any& operator=(any&& rhs) noexcept;
4
Effects: As if by any(std::move(rhs)).swap(*this).
5
Returns: *this.
6
Postconditions: The state of *this is equivalent to the original state of rhs and rhs is left in a valid
but otherwise unspecified state.
template<class T>
any& operator=(T&& rhs);
7
Let VT be decay_t<T>.
8
Requires: VT shall satisfy the CopyConstructible requirements.
9
Effects: Constructs an object tmp of type any that contains an object of type VT direct-initialized with
std::forward<T>(rhs), and tmp.swap(*this). No effects if an exception is thrown.
10
Returns: *this.
11
Remarks: This operator shall not participate in overload resolution unless VT is not the same type as
any and is_copy_constructible_v<VT> is true.
12
Throws: Any exception thrown by the selected constructor of VT.
23.8.3.3
Modifiers
[any.modifiers]
template<class T, class... Args>
decay_t<T>& emplace(Args&&... args);
1
Let VT be decay_t<T>.
2
Requires: VT shall satisfy the CopyConstructible requirements.
3
Effects: Calls reset(). Then initializes the contained value as if direct-non-list-initializing an object of
type VT with the arguments std::forward<Args>(args)
4
Postconditions: *this contains a value.
5
Returns: A reference to the new contained value.
§ 23.8.3.3
531
|
|