22 General utilities library [utilities]
22.4.6 Calling a function with a tuple of arguments [tuple.apply]
22.7 Storage for any type [any]
22.8.5 Class template specialization bad_expected_access<void> [expected.bad.void]
22.8.7 Partial specialization of expected for void types [expected.void]
22.10.6 Class template reference_wrapper [refwrap]
This Clause describes utilities that are generally useful in C++ programs; some
of these utilities are used by other elements of the C++ standard library
. These utilities are summarized in Table
66.The header
contains some basic function and class templates that are used
throughout the rest of the library
.
#include <compare>
#include <initializer_list>
namespace std {
template<class T>
constexpr void swap(T& a, T& b) noexcept(see below);
template<class T, size_t N>
constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>);
template<class T, class U = T>
constexpr T exchange(T& obj, U&& new_val) noexcept(see below);
template<class T>
constexpr T&& forward(remove_reference_t<T>& t) noexcept;
template<class T>
constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
template<class T, class U>
constexpr auto forward_like(U&& x) noexcept -> see below;
template<class T>
constexpr remove_reference_t<T>&& move(T&&) noexcept;
template<class T>
constexpr conditional_t<
!is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&>
move_if_noexcept(T& x) noexcept;
template<class T>
constexpr add_const_t<T>& as_const(T& t) noexcept;
template<class T>
void as_const(const T&&) = delete;
template<class T>
add_rvalue_reference_t<T> declval() noexcept;
template<class T, class U>
constexpr bool cmp_equal(T t, U u) noexcept;
template<class T, class U>
constexpr bool cmp_not_equal(T t, U u) noexcept;
template<class T, class U>
constexpr bool cmp_less(T t, U u) noexcept;
template<class T, class U>
constexpr bool cmp_greater(T t, U u) noexcept;
template<class T, class U>
constexpr bool cmp_less_equal(T t, U u) noexcept;
template<class T, class U>
constexpr bool cmp_greater_equal(T t, U u) noexcept;
template<class R, class T>
constexpr bool in_range(T t) noexcept;
template<class T>
constexpr underlying_type_t<T> to_underlying(T value) noexcept;
[[noreturn]] void unreachable();
void observable_checkpoint() noexcept;
template<class T, T...>
struct integer_sequence;
template<size_t... I>
using index_sequence = integer_sequence<size_t, I...>;
template<class T, T N>
using make_integer_sequence = integer_sequence<T, see below>;
template<size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;
template<class... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>;
template<class T1, class T2>
struct pair;
template<class T1, class T2, class U1, class U2,
template<class> class TQual, template<class> class UQual>
requires requires { typename pair<common_reference_t<TQual<T1>, UQual<U1>>,
common_reference_t<TQual<T2>, UQual<U2>>>; }
struct basic_common_reference<pair<T1, T2>, pair<U1, U2>, TQual, UQual> {
using type = pair<common_reference_t<TQual<T1>, UQual<U1>>,
common_reference_t<TQual<T2>, UQual<U2>>>;
};
template<class T1, class T2, class U1, class U2>
requires requires { typename pair<common_type_t<T1, U1>, common_type_t<T2, U2>>; }
struct common_type<pair<T1, T2>, pair<U1, U2>> {
using type = pair<common_type_t<T1, U1>, common_type_t<T2, U2>>;
};
template<class T1, class T2, class U1, class U2>
constexpr bool operator==(const pair<T1, T2>&, const pair<U1, U2>&);
template<class T1, class T2, class U1, class U2>
constexpr common_comparison_category_t<synth-three-way-result<T1, U1>,
synth-three-way-result<T2, U2>>
operator<=>(const pair<T1, T2>&, const pair<U1, U2>&);
template<class T1, class T2>
constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
template<class T1, class T2>
constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y)
noexcept(noexcept(x.swap(y)));
template<class T1, class T2>
constexpr see below make_pair(T1&&, T2&&);
template<class T> struct tuple_size;
template<size_t I, class T> struct tuple_element;
template<class T1, class T2> struct tuple_size<pair<T1, T2>>;
template<size_t I, class T1, class T2> struct tuple_element<I, pair<T1, T2>>;
template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>&) noexcept;
template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&&) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>&) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&&) noexcept;
template<class T1, class T2>
constexpr T1& get(pair<T1, T2>& p) noexcept;
template<class T1, class T2>
constexpr const T1& get(const pair<T1, T2>& p) noexcept;
template<class T1, class T2>
constexpr T1&& get(pair<T1, T2>&& p) noexcept;
template<class T1, class T2>
constexpr const T1&& get(const pair<T1, T2>&& p) noexcept;
template<class T2, class T1>
constexpr T2& get(pair<T1, T2>& p) noexcept;
template<class T2, class T1>
constexpr const T2& get(const pair<T1, T2>& p) noexcept;
template<class T2, class T1>
constexpr T2&& get(pair<T1, T2>&& p) noexcept;
template<class T2, class T1>
constexpr const T2&& get(const pair<T1, T2>&& p) noexcept;
struct piecewise_construct_t {
explicit piecewise_construct_t() = default;
};
inline constexpr piecewise_construct_t piecewise_construct{};
template<class... Types> class tuple;
struct in_place_t {
explicit in_place_t() = default;
};
inline constexpr in_place_t in_place{};
template<class T>
struct in_place_type_t {
explicit in_place_type_t() = default;
};
template<class T> constexpr in_place_type_t<T> in_place_type{};
template<size_t I>
struct in_place_index_t {
explicit in_place_index_t() = default;
};
template<size_t I> constexpr in_place_index_t<I> in_place_index{};
template<auto V>
struct nontype_t {
explicit nontype_t() = default;
};
template<auto V> constexpr nontype_t<V> nontype{};
struct monostate;
constexpr bool operator==(monostate, monostate) noexcept;
constexpr strong_ordering operator<=>(monostate, monostate) noexcept;
template<class T> struct hash;
template<> struct hash<monostate>;
}
template<class T>
constexpr void swap(T& a, T& b) noexcept(see below);
Constraints:
is_move_constructible_v<T> is
true and
is_move_assignable_v<T> is
true. Effects: Exchanges values stored in two locations
. Remarks: The exception specification is equivalent to:
is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>
template<class T, size_t N>
constexpr void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>);
Constraints:
is_swappable_v<T> is
true. Effects: As if by
swap_ranges(a, a + N, b). template<class T, class U = T>
constexpr T exchange(T& obj, U&& new_val) noexcept(see below);
Effects: Equivalent to:
T old_val = std::move(obj);
obj = std::forward<U>(new_val);
return old_val;
Remarks: The exception specification is equivalent to:
is_nothrow_move_constructible_v<T> && is_nothrow_assignable_v<T&, U>
The library provides templated helper functions to simplify
applying move semantics to an lvalue and to simplify the implementation
of forwarding functions
. template<class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept;
template<class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
Mandates: For the second overload,
is_lvalue_reference_v<T> is
false. Returns:
static_cast<T&&>(t). [
Example 1:
template<class T, class A1, class A2>
shared_ptr<T> factory(A1&& a1, A2&& a2) {
return shared_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2)));
}
struct A {
A(int&, const double&);
};
void g() {
shared_ptr<A> sp1 = factory<A>(2, 1.414);
int i = 2;
shared_ptr<A> sp2 = factory<A>(i, 1.414);
}
In the first call to
factory,
A1 is deduced as
int, so 2 is forwarded
to
A's constructor as an rvalue
. In the second call to
factory,
A1 is deduced as
int&, so
i is forwarded
to
A's constructor as an lvalue
. In
both cases,
A2 is deduced as
double, so
1.414 is forwarded to
A's constructor as an rvalue
. —
end example]
template<class T, class U>
constexpr auto forward_like(U&& x) noexcept -> see below;
Let
COPY_CONST(A, B) be
const B
if
A is a const type, otherwise
B.Let
OVERRIDE_REF(A, B) be
remove_reference_t<B>&&
if
A is an rvalue reference type, otherwise
B&.Let V be
OVERRIDE_REF(T&&, COPY_CONST(remove_reference_t<T>, remove_reference_t<U>))
Returns:
static_cast<V>(x). Remarks: The return type is
V. [
Example 2:
struct accessor {
vector<string>* container;
decltype(auto) operator[](this auto&& self, size_t i) {
return std::forward_like<decltype(self)>((*container)[i]);
}
};
void g() {
vector v{"a"s, "b"s};
accessor a{&v};
string& x = a[0];
string&& y = std::move(a)[0];
string const&& z = std::move(as_const(a))[1];
string& w = as_const(a)[1];
}
—
end example]
template<class T> constexpr remove_reference_t<T>&& move(T&& t) noexcept;
Returns:
static_cast<remove_reference_t<T>&&>(t). [
Example 3:
template<class T, class A1>
shared_ptr<T> factory(A1&& a1) {
return shared_ptr<T>(new T(std::forward<A1>(a1)));
}
struct A {
A();
A(const A&);
A(A&&);
};
void g() {
A a;
shared_ptr<A> sp1 = factory<A>(a);
shared_ptr<A> sp2 = factory<A>(std::move(a));
}
In the first call to
factory,
A1 is deduced as
A&, so
a is forwarded
as a non-const lvalue
. This binds to the constructor
A(const A&),
which copies the value from
a. In the second call to
factory, because of the call
std::move(a),
A1 is deduced as
A, so
a is forwarded
as an rvalue
. This binds to the constructor
A(A&&),
which moves the value from
a. —
end example]
template<class T> constexpr conditional_t<
!is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&>
move_if_noexcept(T& x) noexcept;
template<class T> constexpr add_const_t<T>& as_const(T& t) noexcept;
The library provides the function template
declval to simplify the definition of
expressions which occur as
unevaluated operands.template<class T> add_rvalue_reference_t<T> declval() noexcept;
Remarks: The template parameter
T of
declval may be an incomplete type
. [
Example 1:
template<class To, class From> decltype(static_cast<To>(declval<From>())) convert(From&&);
declares a function template
convert which only participates in overload resolution if the
type
From can be explicitly converted to type
To. —
end example]
template<class T, class U>
constexpr bool cmp_equal(T t, U u) noexcept;
Effects: Equivalent to:
using UT = make_unsigned_t<T>;
using UU = make_unsigned_t<U>;
if constexpr (is_signed_v<T> == is_signed_v<U>)
return t == u;
else if constexpr (is_signed_v<T>)
return t < 0 ? false : UT(t) == u;
else
return u < 0 ? false : t == UU(u);
template<class T, class U>
constexpr bool cmp_not_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_equal(t, u);
template<class T, class U>
constexpr bool cmp_less(T t, U u) noexcept;
Effects: Equivalent to:
using UT = make_unsigned_t<T>;
using UU = make_unsigned_t<U>;
if constexpr (is_signed_v<T> == is_signed_v<U>)
return t < u;
else if constexpr (is_signed_v<T>)
return t < 0 ? true : UT(t) < u;
else
return u < 0 ? false : t < UU(u);
template<class T, class U>
constexpr bool cmp_greater(T t, U u) noexcept;
Effects: Equivalent to: return cmp_less(u, t);
template<class T, class U>
constexpr bool cmp_less_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_greater(t, u);
template<class T, class U>
constexpr bool cmp_greater_equal(T t, U u) noexcept;
Effects: Equivalent to: return !cmp_less(t, u);
template<class R, class T>
constexpr bool in_range(T t) noexcept;
Effects: Equivalent to:
return cmp_greater_equal(t, numeric_limits<R>::min()) &&
cmp_less_equal(t, numeric_limits<R>::max());
[
Note 1:
These function templates cannot be used to compare
byte,
char,
char8_t,
char16_t,
char32_t,
wchar_t, and
bool. —
end note]
template<class T>
constexpr underlying_type_t<T> to_underlying(T value) noexcept;
Returns:
static_cast<underlying_type_t<T>>(value). [[noreturn]] void unreachable();
Preconditions:
false is
true. [
Note 1:
This precondition cannot be satisfied, thus the behavior
of calling
unreachable is undefined
. —
end note]
[
Example 1:
int f(int x) {
switch (x) {
case 0:
case 1:
return x;
default:
std::unreachable();
}
}
int a = f(1);
int b = f(3);
—
end example]
void observable_checkpoint() noexcept;
The library provides a template for heterogeneous pairs of values
. The library also provides a matching function template to simplify
their construction and several templates that provide access to
pair
objects as if they were
tuple objects (see
[tuple.helper]
and
[tuple.elem])
. namespace std {
template<class T1, class T2>
struct pair {
using first_type = T1;
using second_type = T2;
T1 first;
T2 second;
pair(const pair&) = default;
pair(pair&&) = default;
constexpr explicit(see below) pair();
constexpr explicit(see below) pair(const T1& x, const T2& y);
template<class U1 = T1, class U2 = T2>
constexpr explicit(see below) pair(U1&& x, U2&& y);
template<class U1, class U2>
constexpr explicit(see below) pair(pair<U1, U2>& p);
template<class U1, class U2>
constexpr explicit(see below) pair(const pair<U1, U2>& p);
template<class U1, class U2>
constexpr explicit(see below) pair(pair<U1, U2>&& p);
template<class U1, class U2>
constexpr explicit(see below) pair(const pair<U1, U2>&& p);
template<pair-like P>
constexpr explicit(see below) pair(P&& p);
template<class... Args1, class... Args2>
constexpr pair(piecewise_construct_t,
tuple<Args1...> first_args, tuple<Args2...> second_args);
constexpr pair& operator=(const pair& p);
constexpr const pair& operator=(const pair& p) const;
template<class U1, class U2>
constexpr pair& operator=(const pair<U1, U2>& p);
template<class U1, class U2>
constexpr const pair& operator=(const pair<U1, U2>& p) const;
constexpr pair& operator=(pair&& p) noexcept(see below);
constexpr const pair& operator=(pair&& p) const;
template<class U1, class U2>
constexpr pair& operator=(pair<U1, U2>&& p);
template<class U1, class U2>
constexpr const pair& operator=(pair<U1, U2>&& p) const;
template<pair-like P>
constexpr pair& operator=(P&& p);
template<pair-like P>
constexpr const pair& operator=(P&& p) const;
constexpr void swap(pair& p) noexcept(see below);
constexpr void swap(const pair& p) const noexcept(see below);
};
template<class T1, class T2>
pair(T1, T2) -> pair<T1, T2>;
}
Constructors and member functions of
pair do not throw exceptions unless one of
the element-wise operations specified to be called for that operation
throws an exception
.The defaulted move and copy constructor, respectively, of
pair
is a constexpr function if and only if all required element-wise
initializations for move and copy, respectively,
would be constexpr-suitable (
[dcl.constexpr])
.If
(is_trivially_destructible_v<T1> && is_trivially_destructible_v<T2>)
is
true, then the destructor of
pair is trivial
.pair<T, U> is a structural type (
[temp.param])
if
T and
U are both structural types
. Two values
p1 and
p2 of type
pair<T, U>
are template-argument-equivalent (
[temp.type]) if and only if
p1.first and
p2.first are template-argument-equivalent and
p1.second and
p2.second are template-argument-equivalent
.constexpr explicit(see below) pair();
Constraints:
- is_default_constructible_v<T1> is true and
- is_default_constructible_v<T2> is true.
Effects: Value-initializes
first and
second. Remarks: The expression inside
explicit evaluates to
true
if and only if either
T1 or
T2 is not implicitly default-constructible
. [
Note 1:
This behavior can be implemented with a trait that checks
whether a
const T1& or a
const T2&
can be initialized with
{}. —
end note]
constexpr explicit(see below) pair(const T1& x, const T2& y);
Constraints:
- is_copy_constructible_v<T1> is true and
- is_copy_constructible_v<T2> is true.
Effects: Initializes
first with
x and
second with
y. Remarks: The expression inside explicit is equivalent to:
!is_convertible_v<const T1&, T1> || !is_convertible_v<const T2&, T2>
template<class U1 = T1, class U2 = T2> constexpr explicit(see below) pair(U1&& x, U2&& y);
Constraints:
- is_constructible_v<T1, U1> is true and
- is_constructible_v<T2, U2> is true.
Effects: Initializes
first with
std::forward<U1>(x) and
second
with
std::forward<U2>(y). Remarks: The expression inside explicit is equivalent to:
!is_convertible_v<U1, T1> || !is_convertible_v<U2, T2>
This constructor is defined as deleted if
reference_constructs_from_temporary_v<first_type, U1&&>
is
true or
reference_constructs_from_temporary_v<second_type, U2&&>
is
true.template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>& p);
template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p);
template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p);
template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>&& p);
template<pair-like P> constexpr explicit(see below) pair(P&& p);
Let
FWD(u) be
static_cast<decltype(u)>(u).Constraints:
- For the last overload,
remove_cvref_t<P> is not a specialization of ranges::subrange,
- is_constructible_v<T1, decltype(get<0>(FWD(p)))>
is true, and
- is_constructible_v<T2, decltype(get<1>(FWD(p)))>
is true.
Effects: Initializes
first with
get<0>(FWD(p)) and
second with
get<1>(FWD(p)). Remarks: The expression inside explicit is equivalent to:
!is_convertible_v<decltype(get<0>(FWD(p))), T1> ||
!is_convertible_v<decltype(get<1>(FWD(p))), T2>
The constructor is defined as deleted if
reference_constructs_from_temporary_v<first_type, decltype(get<0>(FWD(p)))> ||
reference_constructs_from_temporary_v<second_type, decltype(get<1>(FWD(p)))>
is
true.template<class... Args1, class... Args2>
constexpr pair(piecewise_construct_t,
tuple<Args1...> first_args, tuple<Args2...> second_args);
Mandates:
- is_constructible_v<T1, Args1...> is true and
- is_constructible_v<T2, Args2...> is true.
Effects: Initializes
first with arguments of types
Args1... obtained by forwarding the elements of
first_args
and initializes
second with arguments of types
Args2...
obtained by forwarding the elements of
second_args. (Here, forwarding
an element
x of type
U within a
tuple object means calling
std::forward<U>(x).)
This form of construction, whereby constructor
arguments for
first and
second are each provided in a separate
tuple object, is called
piecewise construction. [
Note 2:
If a data member of
pair is of reference type and
its initialization binds it to a temporary object,
the program is ill-formed (
[class.base.init])
. —
end note]
constexpr pair& operator=(const pair& p);
Effects: Assigns
p.first to
first and
p.second to
second. Remarks: This operator is defined as deleted unless
is_copy_assignable_v<T1> is
true and
is_copy_assignable_v<T2> is
true. constexpr const pair& operator=(const pair& p) const;
Constraints:
- is_copy_assignable_v<const T1> is true and
- is_copy_assignable_v<const T2> is true.
Effects: Assigns
p.first to
first and
p.second to
second. template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p);
Constraints:
- is_assignable_v<T1&, const U1&> is true and
- is_assignable_v<T2&, const U2&> is true.
Effects: Assigns
p.first to
first and
p.second to
second. template<class U1, class U2> constexpr const pair& operator=(const pair<U1, U2>& p) const;
Constraints:
- is_assignable_v<const T1&, const U1&> is true, and
- is_assignable_v<const T2&, const U2&> is true.
Effects: Assigns
p.first to
first and
p.second to
second. constexpr pair& operator=(pair&& p) noexcept(see below);
Constraints:
- is_move_assignable_v<T1> is true and
- is_move_assignable_v<T2> is true.
Effects: Assigns
std::forward<T1>(p.first) to
first and
std::forward<T2>(p.second) to
second. Remarks: The exception specification is equivalent to:
is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
constexpr const pair& operator=(pair&& p) const;
Constraints:
- is_assignable_v<const T1&, T1> is true and
- is_assignable_v<const T2&, T2> is true.
Effects: Assigns
std::forward<T1>(p.first) to
first and
std::forward<T2>(p.second) to
second. template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p);
Constraints:
- is_assignable_v<T1&, U1> is true and
- is_assignable_v<T2&, U2> is true.
Effects: Assigns
std::forward<U1>(p.first) first and
std::forward<U2>(p.second) to
second. template<pair-like P> constexpr pair& operator=(P&& p);
Constraints:
- different-from<P, pair> ([range.utility.helpers])
is true,
- remove_cvref_t<P> is not a specialization of ranges::subrange,
- is_assignable_v<T1&, decltype(get<0>(std::forward<P>(p)))>
is true, and
- is_assignable_v<T2&, decltype(get<1>(std::forward<P>(p)))>
is true.
Effects: Assigns
get<0>(std::forward<P>(p)) to
first and
get<1>(std::forward<P>(p)) to
second. template<pair-like P> constexpr const pair& operator=(P&& p) const;
Constraints:
- different-from<P, pair> ([range.utility.helpers])
is true,
- remove_cvref_t<P> is not a specialization of ranges::subrange,
- is_assignable_v<const T1&, decltype(get<0>(std::forward<P>(p)))>
is true, and
- is_assignable_v<const T2&, decltype(get<1>(std::forward<P>(p)))>
is true.
Effects: Assigns
get<0>(std::forward<P>(p)) to
first and
get<1>(std::forward<P>(p)) to
second. template<class U1, class U2> constexpr const pair& operator=(pair<U1, U2>&& p) const;
Constraints:
- is_assignable_v<const T1&, U1> is true, and
- is_assignable_v<const T2&, U2> is true.
Effects: Assigns
std::forward<U1>(p.first) to
first and
std::forward<U2>(u.second) to
second. constexpr void swap(pair& p) noexcept(see below);
constexpr void swap(const pair& p) const noexcept(see below);
Mandates:
For the first overload,
is_swappable_v<T1> is
true and
is_swappable_v<T2> is
true.For the second overload,
is_swappable_v<const T1> is
true and
is_swappable_v<const T2> is
true.
Effects: Swaps
first with
p.first and
second with
p.second. Remarks: The exception specification is equivalent to:
- is_nothrow_swappable_v<T1> && is_nothrow_swappable_v<T2>
for the first overload, and
- is_nothrow_swappable_v<const T1> && is_nothrow_swappable_v<const T2>
for the second overload.
template<class T1, class T2, class U1, class U2>
constexpr bool operator==(const pair<T1, T2>& x, const pair<U1, U2>& y);
Constraints:
x.first == y.first and
x.second == y.second are
valid expressions and
each of
decltype(x.first == y.first) and
decltype(x.second == y.second) models
boolean-
testable. Returns:
x.first == y.first && x.second == y.second. template<class T1, class T2, class U1, class U2>
constexpr common_comparison_category_t<synth-three-way-result<T1, U1>,
synth-three-way-result<T2, U2>>
operator<=>(const pair<T1, T2>& x, const pair<U1, U2>& y);
Effects: Equivalent to:
if (auto c = synth-three-way(x.first, y.first); c != 0) return c;
return synth-three-way(x.second, y.second);
template<class T1, class T2>
constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
template<class T1, class T2>
constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
Constraints:
For the first overload,
is_swappable_v<T1> is
true and
is_swappable_v<T2> is
true.For the second overload,
is_swappable_v<const T1> is
true and
is_swappable_v<const T2> is
true.
Effects: Equivalent to
x.swap(y). template<class T1, class T2>
constexpr pair<unwrap_ref_decay_t<T1>, unwrap_ref_decay_t<T2>> make_pair(T1&& x, T2&& y);
Returns: pair<unwrap_ref_decay_t<T1>,
unwrap_ref_decay_t<T2>>(std::forward<T1>(x), std::forward<T2>(y))
[
Example 1:
In place of:
return pair<int, double>(5, 3.1415926);
a C++ program may contain:
return make_pair(5, 3.1415926);
—
end example]
template<class T1, class T2>
struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };
template<size_t I, class T1, class T2>
struct tuple_element<I, pair<T1, T2>> {
using type = see below ;
};
Type: The type
T1 if
I is 0, otherwise the type
T2. template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>& p) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>& p) noexcept;
template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&& p) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&& p) noexcept;
Returns:
If
I is 0, returns a reference to
p.first.If
I is 1, returns a reference to
p.second.
template<class T1, class T2>
constexpr T1& get(pair<T1, T2>& p) noexcept;
template<class T1, class T2>
constexpr const T1& get(const pair<T1, T2>& p) noexcept;
template<class T1, class T2>
constexpr T1&& get(pair<T1, T2>&& p) noexcept;
template<class T1, class T2>
constexpr const T1&& get(const pair<T1, T2>&& p) noexcept;
Mandates:
T1 and
T2 are distinct types
. Returns: A reference to
p.first. template<class T2, class T1>
constexpr T2& get(pair<T1, T2>& p) noexcept;
template<class T2, class T1>
constexpr const T2& get(const pair<T1, T2>& p) noexcept;
template<class T2, class T1>
constexpr T2&& get(pair<T1, T2>&& p) noexcept;
template<class T2, class T1>
constexpr const T2&& get(const pair<T1, T2>&& p) noexcept;
Mandates:
T1 and
T2 are distinct types
. Returns: A reference to
p.second. struct piecewise_construct_t {
explicit piecewise_construct_t() = default;
};
inline constexpr piecewise_construct_t piecewise_construct{};
The
struct piecewise_construct_t is an empty class type
used as a unique type to disambiguate constructor and function overloading
. Specifically,
pair has a constructor with
piecewise_construct_t as the
first argument, immediately followed by two
tuple arguments used
for piecewise construction of the elements of the
pair object
.Subclause
[tuple] describes the tuple library that provides a tuple type as
the class template
tuple that can be instantiated with any number
of arguments
. Each template argument specifies
the type of an element in the
tuple. Consequently, tuples are
heterogeneous, fixed-size collections of values
. An instantiation of
tuple with
two arguments is similar to an instantiation of
pair with the same two arguments
. In addition to being available via inclusion of the
header,
ignore (
[tuple.syn]) is available when
(
[utility]) is included
.A type
T models and satisfies
the exposition-only concept
tuple-like
if
remove_cvref_t<T> is a specialization of
array,
complex,
pair,
tuple, or
ranges::subrange.namespace std {
template<class... Types>
class tuple {
public:
constexpr explicit(see below) tuple();
constexpr explicit(see below) tuple(const Types&...);
template<class... UTypes>
constexpr explicit(see below) tuple(UTypes&&...);
tuple(const tuple&) = default;
tuple(tuple&&) = default;
template<class... UTypes>
constexpr explicit(see below) tuple(tuple<UTypes...>&);
template<class... UTypes>
constexpr explicit(see below) tuple(const tuple<UTypes...>&);
template<class... UTypes>
constexpr explicit(see below) tuple(tuple<UTypes...>&&);
template<class... UTypes>
constexpr explicit(see below) tuple(const tuple<UTypes...>&&);
template<class U1, class U2>
constexpr explicit(see below) tuple(pair<U1, U2>&);
template<class U1, class U2>
constexpr explicit(see below) tuple(const pair<U1, U2>&);
template<class U1, class U2>
constexpr explicit(see below) tuple(pair<U1, U2>&&);
template<class U1, class U2>
constexpr explicit(see below) tuple(const pair<U1, U2>&&);
template<tuple-like UTuple>
constexpr explicit(see below) tuple(UTuple&&);
template<class Alloc>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a);
template<class Alloc>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const Types&...);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&&);
template<class Alloc, tuple-like UTuple>
constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTuple&&);
constexpr tuple& operator=(const tuple&);
constexpr const tuple& operator=(const tuple&) const;
constexpr tuple& operator=(tuple&&) noexcept(see below);
constexpr const tuple& operator=(tuple&&) const;
template<class... UTypes>
constexpr tuple& operator=(const tuple<UTypes...>&);
template<class... UTypes>
constexpr const tuple& operator=(const tuple<UTypes...>&) const;
template<class... UTypes>
constexpr tuple& operator=(tuple<UTypes...>&&);
template<class... UTypes>
constexpr const tuple& operator=(tuple<UTypes...>&&) const;
template<class U1, class U2>
constexpr tuple& operator=(const pair<U1, U2>&);
template<class U1, class U2>
constexpr const tuple& operator=(const pair<U1, U2>&) const;
template<class U1, class U2>
constexpr tuple& operator=(pair<U1, U2>&&);
template<class U1, class U2>
constexpr const tuple& operator=(pair<U1, U2>&&) const;
template<tuple-like UTuple>
constexpr tuple& operator=(UTuple&&);
template<tuple-like UTuple>
constexpr const tuple& operator=(UTuple&&) const;
constexpr void swap(tuple&) noexcept(see below);
constexpr void swap(const tuple&) const noexcept(see below);
};
template<class... UTypes>
tuple(UTypes...) -> tuple<UTypes...>;
template<class T1, class T2>
tuple(pair<T1, T2>) -> tuple<T1, T2>;
template<class Alloc, class... UTypes>
tuple(allocator_arg_t, Alloc, UTypes...) -> tuple<UTypes...>;
template<class Alloc, class T1, class T2>
tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>;
template<class Alloc, class... UTypes>
tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>;
}
If a program declares an explicit or partial specialization of
tuple,
the program is ill-formed, no diagnostic required
.In the descriptions that follow, let
i be in the range
[
0, sizeof...(Types)) in order,
Ti
be the
ith type in
Types, and
Ui be the
ith type in a template parameter pack named
UTypes, where indexing
is zero-based
.For each
tuple constructor, an exception is thrown only if the construction of
one of the types in
Types throws an exception
.The defaulted move and copy constructor, respectively, of
tuple is a constexpr function if and only if all
required element-wise initializations for move and copy, respectively,
would be constexpr-suitable (
[dcl.constexpr])
. The defaulted move and copy constructor of
tuple<> are
constexpr functions
.If
is_trivially_destructible_v<Ti> is
true for all
Ti,
then the destructor of
tuple is trivial
.The default constructor of
tuple<> is trivial
.constexpr explicit(see below) tuple();
Constraints:
is_default_constructible_v<Ti> is
true for all
i. Effects: Value-initializes each element
. Remarks: The expression inside
explicit evaluates to
true
if and only if
Ti is not
copy-list-initializable from an empty list
for at least one
i. [
Note 1:
This behavior can be implemented with a trait that checks whether
a
const Ti& can be initialized with
{}. —
end note]
constexpr explicit(see below) tuple(const Types&...);
Constraints:
sizeof...(Types) ≥ 1 and
is_copy_constructible_v<Ti> is
true for all
i. Effects: Initializes each element with the value of the
corresponding parameter
. Remarks: The expression inside explicit is equivalent to:
!conjunction_v<is_convertible<const Types&, Types>...>
template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&... u);
Let
disambiguating-constraint be:
- negation<is_same<remove_cvref_t<U0>, tuple>>
if sizeof...(Types) is 1;
- otherwise,
bool_constant<!is_same_v<remove_cvref_t<U0>, allocator_arg_t> ||
is_-
same_v<remove_cvref_t<T0>, allocator_arg_t>>
if sizeof...(Types) is 2 or 3; - otherwise, true_type.
Constraints:
- sizeof...(Types) equals sizeof...(UTypes),
- sizeof...(Types) ≥ 1, and
- conjunction_v<disambiguating-constraint,
is_constructible<Types, UTypes>...> is
true.
Effects: Initializes the elements in the tuple with the
corresponding value in
std::forward<UTypes>(u). Remarks: The expression inside explicit is equivalent to:
!conjunction_v<is_convertible<UTypes, Types>...>
This constructor is defined as deleted if
(reference_constructs_from_temporary_v<Types, UTypes&&> || ...)
is
true.tuple(const tuple& u) = default;
Mandates:
is_copy_constructible_v<Ti> is
true for all
i. Effects: Initializes each element of
*this with the
corresponding element of
u. tuple(tuple&& u) = default;
Constraints:
is_move_constructible_v<Ti> is
true for all
i. Effects: For all
i, initializes the
ith element of
*this with
std::forward<Ti>(get<i>(u)). template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>& u);
template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u);
template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u);
template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>&& u);
Let
I be the pack
0, 1, …, (sizeof...(Types) - 1). Let
FWD(u) be
static_cast<decltype(u)>(u).Constraints:
- sizeof...(Types) equals sizeof...(UTypes), and
- (is_constructible_v<Types, decltype(get<I>(FWD(u)))> && ...)
is true, and
- either sizeof...(Types) is not 1, or
(when Types... expands to T and
UTypes... expands to U)
is_convertible_v<decltype(u), T>,
is_constructible_v<T, decltype(u)>, and
is_same_v<T, U> are all false.
Effects: For all
i, initializes the
ith element of
*this
with
get<i>(FWD(u)). Remarks: The expression inside explicit is equivalent to:
!(is_convertible_v<decltype(get<I>(FWD(u))), Types> && ...)
The constructor is defined as deleted if
(reference_constructs_from_temporary_v<Types, decltype(get<I>(FWD(u)))> || ...)
is
true.template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>& u);
template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>& u);
template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&& u);
template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>&& u);
Let
FWD(u) be
static_cast<decltype(u)>(u).Constraints:
- sizeof...(Types) is 2,
- is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true, and
- is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
Effects: Initializes the first element with
get<0>(FWD(u)) and
the second element with
get<1>(FWD(u)). Remarks: The expression inside explicit is equivalent to:
!is_convertible_v<decltype(get<0>(FWD(u))), T0> ||
!is_convertible_v<decltype(get<1>(FWD(u))), T1>
The constructor is defined as deleted if
reference_constructs_from_temporary_v<T0, decltype(get<0>(FWD(u)))> ||
reference_constructs_from_temporary_v<T1, decltype(get<1>(FWD(u)))>
is
true.template<tuple-like UTuple>
constexpr explicit(see below) tuple(UTuple&& u);
Let
I be the pack
0, 1, …, (sizeof...(Types) - 1).Constraints:
- different-from<UTuple, tuple> ([range.utility.helpers])
is true,
- remove_cvref_t<UTuple>
is not a specialization of ranges::subrange,
- sizeof...(Types)
equals tuple_size_v<remove_cvref_t<UTuple>>,
- (is_constructible_v<Types, decltype(get<I>(std::forward<UTuple>(u)))> && ...)
is
true, and
- either sizeof...(Types) is not 1, or
(when Types... expands to T)
is_convertible_v<UTuple, T> and
is_constructible_v<T, UTuple> are both false.
Effects: For all
i, initializes the
ith element of
*this with
get<i>(std::forward<UTuple>(u)). Remarks: The expression inside explicit is equivalent to:
!(is_convertible_v<decltype(get<I>(std::forward<UTuple>(u))), Types> && ...)
The constructor is defined as deleted if
(reference_constructs_from_temporary_v<Types, decltype(get<I>(std::forward<UTuple>(u)))>
|| ...)
is
true.template<class Alloc>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a);
template<class Alloc>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const Types&...);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
template<class Alloc>
constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
template<class Alloc, class... UTypes>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
template<class Alloc, class U1, class U2>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&&);
template<class Alloc, tuple-like UTuple>
constexpr explicit(see below)
tuple(allocator_arg_t, const Alloc& a, UTuple&&);
For each
tuple assignment operator, an exception is thrown only if the
assignment of one of the types in
Types throws an exception
. In the function descriptions that follow, let
i be in the range [
0, sizeof...(Types))
in order,
Ti be the
ith type in
Types,
and
Ui be the
ith type in a
template parameter pack named
UTypes, where indexing is zero-based
.constexpr tuple& operator=(const tuple& u);
Effects: Assigns each element of
u to the corresponding
element of
*this. Remarks: This operator is defined as deleted unless
is_copy_assignable_v<Ti> is
true for all
i. constexpr const tuple& operator=(const tuple& u) const;
Constraints:
(is_copy_assignable_v<const Types> && ...) is
true. Effects: Assigns each element of
u to the corresponding element of
*this. constexpr tuple& operator=(tuple&& u) noexcept(see below);
Constraints:
is_move_assignable_v<Ti> is
true for all
i. Effects: For all
i, assigns
std::forward<Ti>(get<i>(u)) to
get<i>(*this). Remarks: The exception specification is equivalent to the logical
and of the
following expressions:
is_nothrow_move_assignable_v<Ti>
where
Ti is the
ith type in
Types. constexpr const tuple& operator=(tuple&& u) const;
Constraints:
(is_assignable_v<const Types&, Types> && ...) is
true. Effects: For all
i,
assigns
std::forward<Ti>(get<i>(u)) to
get<i>(*this). template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>& u);
Constraints:
- sizeof...(Types) equals sizeof...(UTypes) and
- is_assignable_v<Ti&, const Ui&> is true for all i.
Effects: Assigns each element of
u to the corresponding element
of
*this. template<class... UTypes> constexpr const tuple& operator=(const tuple<UTypes...>& u) const;
Constraints:
- sizeof...(Types) equals sizeof...(UTypes) and
- (is_assignable_v<const Types&, const UTypes&> && ...) is true.
Effects: Assigns each element of
u to the corresponding element of
*this. template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&& u);
Constraints:
- sizeof...(Types) equals sizeof...(UTypes) and
- is_assignable_v<Ti&, Ui> is true for all i.
Effects: For all
i, assigns
std::forward<Ui>(get<i>(u)) to
get<i>(*this). template<class... UTypes> constexpr const tuple& operator=(tuple<UTypes...>&& u) const;
Constraints:
- sizeof...(Types) equals sizeof...(UTypes) and
- (is_assignable_v<const Types&, UTypes> && ...) is true.
Effects: For all
i,
assigns
std::forward<Ui>(get<i>(u)) to
get<i>(*this). template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>& u);
Constraints:
- sizeof...(Types) is 2 and
- is_assignable_v<T0&, const U1&> is true, and
- is_assignable_v<T1&, const U2&> is true.
Effects: Assigns
u.first to the first element of
*this
and
u.second to the second element of
*this. template<class U1, class U2> constexpr const tuple& operator=(const pair<U1, U2>& u) const;
Constraints:
- sizeof...(Types) is 2,
- is_assignable_v<const T0&, const U1&> is true, and
- is_assignable_v<const T1&, const U2&> is true.
Effects: Assigns
u.first to the first element and
u.second to the second element
. template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&& u);
Constraints:
- sizeof...(Types) is 2 and
- is_assignable_v<T0&, U1> is true, and
- is_assignable_v<T1&, U2> is true.
Effects: Assigns std::forward<U1>(u.first) to the first
element of *this and
std::forward<U2>(u.second) to the
second element of
*this. template<class U1, class U2> constexpr const tuple& operator=(pair<U1, U2>&& u) const;
Constraints:
- sizeof...(Types) is 2,
- is_assignable_v<const T0&, U1> is true, and
- is_assignable_v<const T1&, U2> is true.
Effects: Assigns std::forward<U1>(u.first) to the first element and
std::forward<U2>(u.second) to the second element
. template<tuple-like UTuple>
constexpr tuple& operator=(UTuple&& u);
Constraints:
- different-from<UTuple, tuple> ([range.utility.helpers])
is true,
- remove_cvref_t<UTuple>
is not a specialization of ranges::subrange,
- sizeof...(Types)
equals tuple_size_v<remove_cvref_t<UTuple>>, and
- is_assignable_v<Ti&, decltype(get<i>(std::forward<UTuple>(u)))>
is true for all i.
Effects: For all
i, assigns
get<i>(std::forward<UTuple>(u))
to
get<i>(*this). template<tuple-like UTuple>
constexpr const tuple& operator=(UTuple&& u) const;
Constraints:
- different-from<UTuple, tuple> ([range.utility.helpers])
is true,
- remove_cvref_t<UTuple>
is not a specialization of ranges::subrange,
- sizeof...(Types)
equals tuple_size_v<remove_cvref_t<UTuple>>, and
- is_assignable_v<const Ti&, decltype(get<i>(std::forward<UTuple>(u)))>
is true for all i.
Effects: For all
i, assigns
get<i>(std::forward<UTuple>(u)) to
get<i>(*this). constexpr void swap(tuple& rhs) noexcept(see below);
constexpr void swap(const tuple& rhs) const noexcept(see below);
Let
i be in the range [
0, sizeof...(Types)) in order
.Mandates:
For the first overload,
(is_swappable_v<Types> && ...) is
true.For the second overload,
(is_swappable_v<const Types> && ...) is
true.
Effects: For each
i, calls
swap for
get<i>(*this) and
get<i>(rhs). Throws: Nothing unless one of the element-wise
swap calls throws an exception
. Remarks: The exception specification is equivalent to
- (is_nothrow_swappable_v<Types> && ...) for the first overload and
- (is_nothrow_swappable_v<const Types> && ...) for the second overload.
template<class... TTypes>
constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&... t);
Returns:
tuple<unwrap_ref_decay_t<TTypes>...>(std::forward<TTypes>(t)...). [
Example 1:
int i; float j;
make_tuple(1, ref(i), cref(j));
creates a tuple of type
tuple<int, int&, const float&>. —
end example]
template<class... TTypes>
constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&... t) noexcept;
Effects: Constructs a tuple of references to the arguments in
t suitable
for forwarding as arguments to a function
. Because the result may contain references
to temporary objects, a program shall ensure that the return value of this
function does not outlive any of its arguments (e.g., the program should typically
not store the result in a named variable)
.Returns:
tuple<TTypes&&...>(std::forward<TTypes>(t)...). template<class... TTypes>
constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
Returns:
tuple<TTypes&...>(t...). [
Example 2:
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++");
—
end example]
template<tuple-like... Tuples>
constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
Let
n be
sizeof...(Tuples). For every integer
0≤i<n:
Let
Ti be the
ith type in
Tuples.Let
Ui be
remove_cvref_t<Ti>.Let
tpi be the
ith element
in the function parameter pack
tpls.Let
Si be
tuple_size_v<Ui>.Let
Eki be
tuple_element_t<k, Ui>.Let
eki be
get<k>(std::forward<Ti>(tpi)).Let
Elemsi be a pack of the types
E0i,…,ESi−1i.Let
elemsi be a pack of the expressions
e0i,…,eSi−1i.
The types in
CTypes are equal to the ordered sequence of
the expanded packs of types
Elems0...,
Elems1..., …,
Elemsn−1.... Let
celems be the ordered sequence of
the expanded packs of expressions
elems0..., …,
elemsn−1....Mandates:
(is_constructible_v<CTypes, decltype(celems)> && ...) is
true. Returns:
tuple<CTypes...>(celems...). template<class F, tuple-like Tuple>
constexpr apply_result_t<F, Tuple> apply(F&& f, Tuple&& t)
noexcept(is_nothrow_applicable_v<F, Tuple>);
Effects: Given the exposition-only function template:
namespace std {
template<class F, tuple-like Tuple, size_t... I>
constexpr decltype(auto) apply-impl(F&& f, Tuple&& t, index_sequence<I...>) {
return INVOKE(std::forward<F>(f), get<I>(std::forward<Tuple>(t))...);
}
}
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, tuple-like Tuple>
constexpr T make_from_tuple(Tuple&& t);
Mandates: If
tuple_size_v<remove_reference_t<Tuple>> is 1,
then
reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))>
is
false. Effects: Given the exposition-only function template:
namespace std {
template<class T, tuple-like Tuple, size_t... I>
requires is_constructible_v<T, decltype(get<I>(declval<Tuple>()))...>
constexpr T make-from-tuple-impl(Tuple&& t, index_sequence<I...>) {
return T(get<I>(std::forward<Tuple>(t))...);
}
}
Equivalent to:
return make-from-tuple-impl<T>(
std::forward<Tuple>(t),
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
[
Note 1:
The type of
T must be supplied
as an explicit template parameter,
as it cannot be deduced from the argument list
. —
end note]
template<class T> struct tuple_size;
Except where specified otherwise,
all specializations of
tuple_size meet the
Cpp17UnaryTypeTrait requirements (
[meta.rqmts]) with a
base characteristic of
integral_constant<size_t, N>
for some
N.template<class... Types>
struct tuple_size<tuple<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
template<size_t I, class... Types>
struct tuple_element<I, tuple<Types...>> {
using type = TI;
};
Mandates:
I < sizeof...(Types). Type:
TI is the
type of the
Ith element of
Types,
where indexing is zero-based
. template<class T> struct tuple_size<const T>;
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 specialization of the template meets the
Cpp17UnaryTypeTrait requirements (
[meta.rqmts])
with a base characteristic of
integral_constant<size_t, TS::value>
Otherwise, it has no member
value.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 1:
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]
In addition to being available via inclusion of the
header,
the template is available
when any of the headers
,
, or
are included
.template<size_t I, class T> struct tuple_element<I, const T>;
Let
TE denote
tuple_element_t<I, T> of the cv-unqualified type
T. In addition to being available via inclusion of the
header,
the template is available
when any of the headers
,
, or
are included
.template<size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&
get(tuple<Types...>& t) noexcept;
template<size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&&
get(tuple<Types...>&& t) noexcept;
template<size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&
get(const tuple<Types...>& t) noexcept;
template<size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
Mandates:
I < sizeof...(Types). Returns: A reference to the
Ith element of
t, where
indexing is zero-based
. [
Note 1:
For the overload marked #1,
if a type
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]
[
Note 2:
For the overload marked #2,
if a type
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 non-static data members 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;
Mandates: The type
T occurs exactly once in
Types. Returns: A reference to the element of
t corresponding to the type
T in
Types. [
Example 1:
const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
const int& i1 = get<int>(t);
const int& i2 = get<const int>(t);
const double& d = get<double>(t);
—
end example]
[
Note 3:
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]
template<class... TTypes, class... UTypes>
constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
template<class... TTypes, tuple-like UTuple>
constexpr bool operator==(const tuple<TTypes...>& t, const UTuple& u);
For the first overload let
UTuple be
tuple<UTypes...>.Constraints: For all
i,
where
0 ≤ i < sizeof...(TTypes),
get<i>(t) == get<i>(u) is a valid expression and
decltype(get<i>(t) == get<i>(u)) models
boolean-testable. sizeof...(TTypes) equals
tuple_size_v<UTuple>. Returns:
true if
get<i>(t) == get<i>(u) for all
i, otherwise
false. [
Note 1:
If
sizeof...(TTypes) equals zero, returns
true. —
end note]
Remarks:
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 common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...>
operator<=>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
template<class... TTypes, tuple-like UTuple>
constexpr common_comparison_category_t<synth-three-way-result<TTypes, Elems>...>
operator<=>(const tuple<TTypes...>& t, const UTuple& u);
For the second overload,
Elems denotes the pack of types
tuple_element_t<0, UTuple>,
tuple_element_t<1, UTuple>, …,
tuple_element_t<tuple_size_v<UTuple> - 1, UTuple>.Effects: Performs a lexicographical comparison between
t and
u. If
sizeof...(TTypes) equals zero,
returns
strong_ordering::equal. Otherwise, equivalent to:
if (auto c = synth-three-way(get<0>(t), get<0>(u)); c != 0) return c;
return ttail <=> utail;
where
rtail for some
r
is a tuple containing all but the first element of
r.[
Note 2:
The above definition does not require
ttail
(or
utail) to be constructed
. It might not
even be possible, as
t and
u are not required to be copy
constructible
. Also, all comparison operator functions are short circuited;
they do not perform element accesses beyond what is needed to determine the
result of the comparison
. —
end note]
In the descriptions that follow:
Let
TTypes be a pack formed by
the sequence of
tuple_element_t<i, TTuple>
for every integer
0≤i<tuple_size_v<TTuple>.Let
UTypes be a pack formed by
the sequence of
tuple_element_t<i, UTuple>
for every integer
0≤i<tuple_size_v<UTuple>.
template<tuple-like TTuple, tuple-like UTuple,
template<class> class TQual, template<class> class UQual>
struct basic_common_reference<TTuple, UTuple, TQual, UQual> {
using type = see below;
};
Constraints:
TTuple is a specialization of
tuple or
UTuple is a specialization of
tuple. is_same_v<TTuple, decay_t<TTuple>> is
true. is_same_v<UTuple, decay_t<UTuple>> is
true. tuple_size_v<TTuple> equals
tuple_size_v<UTuple>. tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>
denotes a type
.
The member
typedef-name type denotes the type
tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>.template<tuple-like TTuple, tuple-like UTuple>
struct common_type<TTuple, UTuple> {
using type = see below;
};
Constraints:
TTuple is a specialization of
tuple or
UTuple is a specialization of
tuple. is_same_v<TTuple, decay_t<TTuple>> is
true. is_same_v<UTuple, decay_t<UTuple>> is
true. tuple_size_v<TTuple> equals
tuple_size_v<UTuple>. tuple<common_type_t<TTypes, UTypes>...> denotes a type
.
The member
typedef-name type denotes the type
tuple<common_type_t<TTypes, UTypes>...>.template<class... Types, class Alloc>
struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
[
Note 1:
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]
template<class... Types>
constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
template<class... Types>
constexpr void swap(const tuple<Types...>& x, const tuple<Types...>& y) noexcept(see below);
Constraints:
For the first overload,
(is_swappable_v<Types> && ...) is
true.For the second overload,
(is_swappable_v<const Types> && ...) is
true.
Effects: As if by
x.swap(y). Remarks: The exception specification is equivalent to:
noexcept(x.swap(y))
Subclause
[optional] 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
.namespace std {
template<class T>
class optional {
public:
using value_type = T;
using iterator = implementation-defined;
using const_iterator = implementation-defined;
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 = remove_cv_t<T>>
constexpr explicit(see below) optional(U&&);
template<class U>
constexpr explicit(see below) optional(const optional<U>&);
template<class U>
constexpr explicit(see below) optional(optional<U>&&);
constexpr ~optional();
constexpr optional& operator=(nullopt_t) noexcept;
constexpr optional& operator=(const optional&);
constexpr optional& operator=(optional&&) noexcept(see below);
template<class U = remove_cv_t<T>> constexpr optional& operator=(U&&);
template<class U> constexpr optional& operator=(const optional<U>&);
template<class U> constexpr optional& operator=(optional<U>&&);
template<class... Args> constexpr T& emplace(Args&&...);
template<class U, class... Args> constexpr T& emplace(initializer_list<U>, Args&&...);
constexpr void swap(optional&) noexcept(see below);
constexpr iterator begin() noexcept;
constexpr const_iterator begin() const noexcept;
constexpr iterator end() noexcept;
constexpr const_iterator end() const noexcept;
constexpr const T* operator->() const noexcept;
constexpr T* operator->() noexcept;
constexpr const T& operator*() const & noexcept;
constexpr T& operator*() & noexcept;
constexpr T&& operator*() && noexcept;
constexpr const T&& operator*() const && noexcept;
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 = remove_cv_t<T>> constexpr T value_or(U&&) const &;
template<class U = remove_cv_t<T>> constexpr T value_or(U&&) &&;
template<class F> constexpr auto and_then(F&& f) &;
template<class F> constexpr auto and_then(F&& f) &&;
template<class F> constexpr auto and_then(F&& f) const &;
template<class F> constexpr auto and_then(F&& f) const &&;
template<class F> constexpr auto transform(F&& f) &;
template<class F> constexpr auto transform(F&& f) &&;
template<class F> constexpr auto transform(F&& f) const &;
template<class F> constexpr auto transform(F&& f) const &&;
template<class F> constexpr optional or_else(F&& f) &&;
template<class F> constexpr optional or_else(F&& f) const &;
constexpr void reset() noexcept;
private:
T* val;
};
template<class T>
optional(T) -> optional<T>;
}
Any instance of
optional<T> at any given time either contains a value or does not contain a value
. 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.When an
optional<T> object contains a value,
member
val points to the contained value
.A type
X is a
valid contained type for
optional
if
X is an lvalue reference type or a complete non-array object type,
and
remove_cvref_t<X> is a type other than
in_place_t or
nullopt_t. If a specialization of
optional is instantiated with a type
T
that is not a valid contained type for
optional, the program is ill-formed
. If
T is an object type,
T shall meet the
Cpp17Destructible requirements (Table
35)
.The exposition-only variable template
converts-from-any-cvref
is used by some constructors for
optional. template<class T, class W>
constexpr bool converts-from-any-cvref =
disjunction_v<is_constructible<T, W&>, is_convertible<W&, T>,
is_constructible<T, W>, is_convertible<W, T>,
is_constructible<T, const W&>, is_convertible<const W&, T>,
is_constructible<T, const W>, is_convertible<const W, T>>;
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
Postconditions:
*this does not contain a value
. Remarks: No contained value is initialized
. For every object type
T these constructors are constexpr constructors (
[dcl.constexpr])
.constexpr optional(const optional& rhs);
Effects: If
rhs contains a value, direct-non-list-initializes the contained value
with
*rhs. Postconditions:
rhs.has_value() == this->has_value(). Throws: Any exception thrown by the selected constructor of
T. Remarks: This constructor is defined as deleted unless
is_copy_constructible_v<T> is
true. If
is_trivially_copy_constructible_v<T> is
true,
this constructor is trivial
.constexpr optional(optional&& rhs) noexcept(see below);
Constraints:
is_move_constructible_v<T> is
true. Effects: If
rhs contains a value, direct-non-list-initializes the contained value
with
*std::move(rhs). rhs.has_value() is unchanged
. Postconditions:
rhs.has_value() == this->has_value(). Throws: Any exception thrown by the selected constructor of
T. Remarks: The exception specification is equivalent to
is_nothrow_move_constructible_v<T>. If
is_trivially_move_constructible_v<T> is
true,
this constructor is trivial
.template<class... Args> constexpr explicit optional(in_place_t, Args&&... args);
Constraints:
is_constructible_v<T, Args...> is
true. Effects: Direct-non-list-initializes the contained value with
std::forward<Args>(args).... Postconditions:
*this contains a value
. Throws: Any exception thrown by the selected constructor of
T. Remarks: If
T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor
. template<class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
Constraints:
is_constructible_v<T, initializer_list<U>&, Args...> is
true. Effects: Direct-non-list-initializes the contained value with
il, std::forward<Args>(args).... Postconditions:
*this contains a value
. Throws: Any exception thrown by the selected constructor of
T. Remarks: If
T's constructor selected for the initialization is a constexpr constructor, this constructor is a constexpr constructor
. template<class U = remove_cv_t<T>> constexpr explicit(see below) optional(U&& v);
Constraints:
- is_constructible_v<T, U> is true,
- is_same_v<remove_cvref_t<U>, in_place_t> is false,
- is_same_v<remove_cvref_t<U>, optional> is false, and
- if T is cv bool,
remove_cvref_t<U> is not a specialization of optional.
Effects: Direct-non-list-initializes the contained value with
std::forward<U>(v). Postconditions:
*this contains a value
. Throws: Any exception thrown by the selected constructor of
T. Remarks: If
T's selected constructor is a constexpr constructor,
this constructor is a constexpr constructor
. The expression inside explicit is equivalent to:
!is_convertible_v<U, T>
template<class U> constexpr explicit(see below) optional(const optional<U>& rhs);
Constraints:
- is_constructible_v<T, const U&> is true, and
- if T is not cv bool,
converts-from-any-cvref<T, optional<U>> is false.
Effects: If
rhs contains a value,
direct-non-list-initializes the contained value with
*rhs. Postconditions:
rhs.has_value() == this->has_value(). Throws: Any exception thrown by the selected constructor of
T. Remarks: The expression inside explicit is equivalent to:
!is_convertible_v<const U&, T>
template<class U> constexpr explicit(see below) optional(optional<U>&& rhs);
Constraints:
- is_constructible_v<T, U> is true, and
- if T is not cv bool,
converts-from-any-cvref<T, optional<U>> is false.
Effects: If
rhs contains a value,
direct-non-list-initializes the contained value with
*std::move(rhs). rhs.has_value() is unchanged
. Postconditions:
rhs.has_value() == this->has_value(). Throws: Any exception thrown by the selected constructor of
T. Remarks: The expression inside explicit is equivalent to:
!is_convertible_v<U, T>
Effects: If is_trivially_destructible_v<T> != true and *this contains a value, calls
val->T::~T()
Remarks: If
is_trivially_destructible_v<T> is
true, then this destructor is trivial
. constexpr optional<T>& operator=(nullopt_t) noexcept;
Effects: If
*this contains a value, calls
val->T::~T() to destroy the contained value; otherwise no effect
. Postconditions:
*this does not contain a value
. constexpr optional<T>& operator=(const optional& rhs);
Table
67 —
optional::operator=(const optional&) effects
[tab:optional.assign.copy] | | | *this does not contain a value |
| | assigns *rhs to the contained value | direct-non-list-initializes the contained value with *rhs |
rhs does not contain a value | | destroys the contained value by calling val->T::~T() | |
Postconditions:
rhs.has_value() == this->has_value(). Remarks: If any exception is thrown, the result of the expression
this->has_value() 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 is defined as deleted unless
is_copy_constructible_v<T> is
true and
is_copy_assignable_v<T> is
true. If
is_trivially_copy_constructible_v<T> &&
is_trivially_copy_assignable_v<T> &&
is_trivially_destructible_v<T> is
true,
this assignment operator is trivial
.constexpr optional& operator=(optional&& rhs) noexcept(see below);
Constraints:
is_move_constructible_v<T> is
true and
is_move_assignable_v<T> is
true. The result of the expression
rhs.has_value() remains unchanged
. Table
68 —
optional::operator=(optional&&) effects
[tab:optional.assign.move] | | | *this does not contain a value |
| | assigns *std::move(rhs) to the contained value | direct-non-list-initializes the contained value with *std::move(rhs) |
rhs does not contain a value | | destroys the contained value by calling val->T::~T() | |
Postconditions:
rhs.has_value() == this->has_value(). Remarks: The exception specification is equivalent to:
is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>
If any exception is thrown, the result of the expression
this->has_value() 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
. If
is_trivially_move_constructible_v<T> &&
is_trivially_move_assignable_v<T> &&
is_trivially_destructible_v<T> is
true,
this assignment operator is trivial
.template<class U = remove_cv_t<T>> constexpr optional& operator=(U&& v);
Constraints:
- 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.
Effects: If
*this contains a value, assigns
std::forward<U>(v) to the contained value; otherwise direct-non-list-initializes the contained value with
std::forward<U>(v). Postconditions:
*this contains a value
. Remarks: If any exception is thrown, the result of the expression
this->has_value() 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
.template<class U> constexpr optional<T>& operator=(const optional<U>& rhs);
Constraints:
- is_constructible_v<T, const U&> is true,
- is_assignable_v<T&, const U&> is true,
- converts-from-any-cvref<T, optional<U>> is false,
- is_assignable_v<T&, optional<U>&> is false,
- is_assignable_v<T&, optional<U>&&> is false,
- is_assignable_v<T&, const optional<U>&> is false, and
- is_assignable_v<T&, const optional<U>&&> is false.
Table
69 —
optional::operator=(const optional<U>&) effects
[tab:optional.assign.copy.templ] | | | *this does not contain a value |
| | assigns *rhs to the contained value | direct-non-list-initializes the contained value with *rhs |
rhs does not contain a value | | destroys the contained value by calling val->T::~T() | |
Postconditions:
rhs.has_value() == this->has_value(). Remarks: If any exception is thrown,
the result of the expression
this->has_value() 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
.template<class U> constexpr optional<T>& operator=(optional<U>&& rhs);
Constraints:
- is_constructible_v<T, U> is true,
- is_assignable_v<T&, U> is true,
- converts-from-any-cvref<T, optional<U>> is false,
- is_assignable_v<T&, optional<U>&> is false,
- is_assignable_v<T&, optional<U>&&> is false,
- is_assignable_v<T&, const optional<U>&> is false, and
- is_assignable_v<T&, const optional<U>&&> is false.
The result of the expression
rhs.has_value() remains unchanged
. Table
70 —
optional::operator=(optional<U>&&) effects
[tab:optional.assign.move.templ] | | | *this does not contain a value |
| | assigns *std::move(rhs) to the contained value | direct-non-list-initializes the contained value with *std::move(rhs) |
rhs does not contain a value | | destroys the contained value by calling val->T::~T() | |
Postconditions:
rhs.has_value() == this->has_value(). Remarks: If any exception is thrown,
the result of the expression
this->has_value() 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
.template<class... Args> constexpr T& emplace(Args&&... args);
Mandates:
is_constructible_v<T, Args...> is
true. Effects: Calls
*this = nullopt. Then direct-non-list-initializes the contained value
with
std::forward<Args>(args)....Postconditions:
*this contains a value
. Returns: A reference to the new contained value
. Throws: Any exception thrown by the selected constructor of
T. 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> constexpr T& emplace(initializer_list<U> il, Args&&... args);
Constraints:
is_constructible_v<T, initializer_list<U>&, Args...> is
true. Effects: Calls
*this = nullopt. Then direct-non-list-initializes the contained value with
il, std::forward<Args>(args)....Postconditions:
*this contains a value
. Returns: A reference to the new contained value
. Throws: Any exception thrown by the selected constructor of
T. 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
. constexpr void swap(optional& rhs) noexcept(see below);
Mandates:
is_move_constructible_v<T> is
true. Table
71 —
optional::swap(optional&) effects
[tab:optional.swap] | | | *this does not contain a value |
| | calls swap(*(*this), *rhs) | direct-non-list-initializes the contained value of *this
with std::move(*rhs),
followed by rhs.val->T::~T();
postcondition is that *this contains a value and rhs does not contain a value |
rhs does not contain a value | | direct-non-list-initializes the contained value of rhs
with std::move(*(*this)),
followed by val->T::~T();
postcondition is that *this does not contain a value and rhs contains a value | |
Throws: Any exceptions thrown by the operations in the relevant part of Table
71. Remarks: The exception specification is equivalent to:
is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>
If any exception is thrown, the results of the expressions
this->has_value() and
rhs.has_value() 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
.using iterator = implementation-defined;
using const_iterator = implementation-defined;
The reference type is
T& for
iterator and
const T& for
const_iterator. All requirements on container iterators (
[container.reqmts]) apply to
optional::iterator and
optional::const_iterator as well
.Any operation that initializes or destroys the contained value of an optional object invalidates all iterators into that object
.constexpr iterator begin() noexcept;
constexpr const_iterator begin() const noexcept;
Returns: If
has_value() is
true,
an iterator referring to the contained value
. Otherwise, a past-the-end iterator value
.constexpr iterator end() noexcept;
constexpr const_iterator end() const noexcept;
Returns:
begin() + has_value(). constexpr const T* operator->() const noexcept;
constexpr T* operator->() noexcept;
Hardened preconditions:
has_value() is
true. Remarks: These functions are constexpr functions
. constexpr const T& operator*() const & noexcept;
constexpr T& operator*() & noexcept;
Hardened preconditions:
has_value() is
true. Remarks: These functions are constexpr functions
. constexpr T&& operator*() && noexcept;
constexpr const T&& operator*() const && noexcept;
Hardened preconditions:
has_value() is
true. Effects: Equivalent to: return std::move(*val);
constexpr explicit operator bool() const noexcept;
Returns:
true if and only if
*this contains a value
. Remarks: This function is a constexpr function
. constexpr bool has_value() const noexcept;
Returns:
true if and only if
*this contains a value
. Remarks: This function is a constexpr function
. constexpr const T& value() const &;
constexpr T& value() &;
Effects: Equivalent to:
return has_value() ? *val : throw bad_optional_access();
constexpr T&& value() &&;
constexpr const T&& value() const &&;
Effects: Equivalent to:
return has_value() ? std::move(*val) : throw bad_optional_access();
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) const &;
Mandates:
is_copy_constructible_v<T> && is_convertible_v<U&&, T> is
true. Effects: Equivalent to:
return has_value() ? **this : static_cast<T>(std::forward<U>(v));
template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) &&;
Mandates:
is_move_constructible_v<T> && is_convertible_v<U&&, T> is
true. Effects: Equivalent to:
return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
template<class F> constexpr auto and_then(F&& f) &;
template<class F> constexpr auto and_then(F&& f) const &;
Let
U be
invoke_result_t<F, decltype(*val)>.Mandates:
remove_cvref_t<U> is a specialization of
optional. Effects: Equivalent to:
if (*this) {
return invoke(std::forward<F>(f), *val);
} else {
return remove_cvref_t<U>();
}
template<class F> constexpr auto and_then(F&& f) &&;
template<class F> constexpr auto and_then(F&& f) const &&;
Let
U be
invoke_result_t<F, decltype(std::move(*val))>.Mandates:
remove_cvref_t<U> is a specialization of
optional. Effects: Equivalent to:
if (*this) {
return invoke(std::forward<F>(f), std::move(*val));
} else {
return remove_cvref_t<U>();
}
Let
U be
remove_cv_t<invoke_result_t<F, decltype(*val)>>.Mandates:
U is a valid contained type for
optional. The declaration
U u(invoke(std::forward<F>(f), *val));
is well-formed for some invented variable
u. Returns: If
*this contains a value, an
optional<U> object
whose contained value is direct-non-list-initialized with
invoke(std::forward<F>(f), *val);
otherwise,
optional<U>(). Let
U be
remove_cv_t<invoke_result_t<F, decltype(std::move(*val))>>.Mandates:
U is a valid contained type for
optional. The declaration
U u(invoke(std::forward<F>(f), std::move(*val)));
is well-formed for some invented variable
u. Returns: If
*this contains a value, an
optional<U> object
whose contained value is direct-non-list-initialized with
invoke(std::forward<F>(f), std::move(*val));
otherwise,
optional<U>(). template<class F> constexpr optional or_else(F&& f) const &;
Mandates:
is_same_v<remove_cvref_t<invoke_result_t<F>>, optional> is
true. Effects: Equivalent to:
if (*this) {
return *this;
} else {
return std::forward<F>(f)();
}
template<class F> constexpr optional or_else(F&& f) &&;
Mandates:
is_same_v<remove_cvref_t<invoke_result_t<F>>, optional> is
true. Effects: Equivalent to:
if (*this) {
return std::move(*this);
} else {
return std::forward<F>(f)();
}
constexpr void reset() noexcept;
Effects: If
*this contains a value, calls
val->T::~T() to destroy the contained value;
otherwise no effect
. Postconditions:
*this does not contain a value
. namespace std {
template<class T>
class optional<T&> {
public:
using value_type = T;
using iterator = implementation-defined;
public:
constexpr optional() noexcept = default;
constexpr optional(nullopt_t) noexcept : optional() {}
constexpr optional(const optional& rhs) noexcept = default;
template<class Arg>
constexpr explicit optional(in_place_t, Arg&& arg);
template<class U>
constexpr explicit(see below) optional(U&& u) noexcept(see below);
template<class U>
constexpr explicit(see below) optional(optional<U>& rhs) noexcept(see below);
template<class U>
constexpr explicit(see below) optional(const optional<U>& rhs) noexcept(see below);
template<class U>
constexpr explicit(see below) optional(optional<U>&& rhs) noexcept(see below);
template<class U>
constexpr explicit(see below) optional(const optional<U>&& rhs) noexcept(see below);
constexpr ~optional() = default;
constexpr optional& operator=(nullopt_t) noexcept;
constexpr optional& operator=(const optional& rhs) noexcept = default;
template<class U> constexpr T& emplace(U&& u) noexcept(see below);
constexpr void swap(optional& rhs) noexcept;
constexpr iterator begin() const noexcept;
constexpr iterator end() const noexcept;
constexpr T* operator->() const noexcept;
constexpr T& operator*() const noexcept;
constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr T& value() const;
template<class U = remove_cv_t<T>>
constexpr remove_cv_t<T> value_or(U&& u) const;
template<class F> constexpr auto and_then(F&& f) const;
template<class F> constexpr optional<invoke_result_t<F, T&>> transform(F&& f) const;
template<class F> constexpr optional or_else(F&& f) const;
constexpr void reset() noexcept;
private:
T* val = nullptr;
template<class U>
constexpr void convert-ref-init-val(U&& u);
};
}
When an
optional<T&> contains a value,
the
contained value
is a reference to
*val. template<class Arg>
constexpr explicit optional(in_place_t, Arg&& arg);
Constraints:
- is_constructible_v<T&, Arg> is true, and
- reference_constructs_from_temporary_v<T&, Arg> is false.
Effects: Equivalent to:
convert-ref-init-val(std::forward<Arg>(arg)). Postconditions:
*this contains a value
. template<class U>
constexpr explicit(!is_convertible_v<U, T&>)
optional(U&& u) noexcept(is_nothrow_constructible_v<T&, U>);
Constraints:
- is_same_v<remove_cvref_t<U>, optional> is false,
- is_same_v<remove_cvref_t<U>, in_place_t> is false, and
- is_constructible_v<T&, U> is true.
Effects: Equivalent to:
convert-ref-init-val(std::forward<U>(u)). Postconditions:
*this contains a value
. Remarks: This constructor is defined as deleted if
reference_constructs_from_temporary_v<T&, U>
is
true. template<class U>
constexpr explicit(!is_convertible_v<U&, T&>)
optional(optional<U>& rhs) noexcept(is_nothrow_constructible_v<T&, U&>);
Constraints:
- is_same_v<remove_cv_t<T>, optional<U>> is false,
- is_same_v<T&, U> is false, and
- is_constructible_v<T&, U&> is true.
Effects: Equivalent to:
if (rhs.has_value()) convert-ref-init-val(*rhs);
Remarks: This constructor is defined as deleted if
reference_constructs_from_temporary_v<T&, U&>
is
true. template<class U>
constexpr explicit(!is_convertible_v<const U&, T&>)
optional(const optional<U>& rhs) noexcept(is_nothrow_constructible_v<T&, const U&>);
Constraints:
- is_same_v<remove_cv_t<T>, optional<U>> is false,
- is_same_v<T&, U> is false, and
- is_constructible_v<T&, const U&> is true.
Effects: Equivalent to:
if (rhs.has_value()) convert-ref-init-val(*rhs);
Remarks: This constructor is defined as deleted if
reference_constructs_from_temporary_v<T&, const U&>
is
true. template<class U>
constexpr explicit(!is_convertible_v<U, T&>)
optional(optional<U>&& rhs) noexcept(is_nothrow_constructible_v<T&, U>);
Constraints:
- is_same_v<remove_cv_t<T>, optional<U>> is false,
- is_same_v<T&, U> is false, and
- is_constructible_v<T&, U> is true.
Effects: Equivalent to:
if (rhs.has_value()) convert-ref-init-val(*std::move(rhs));
Remarks: This constructor is defined as deleted if
reference_constructs_from_temporary_v<T&, U>
is
true. template<class U>
constexpr explicit(!is_convertible_v<const U, T&>)
optional(const optional<U>&& rhs) noexcept(is_nothrow_constructible_v<T&, const U>);
Constraints:
- is_same_v<remove_cv_t<T>, optional<U>> is false,
- is_same_v<T&, U> is false, and
- is_constructible_v<T&, const U> is true.
Effects: Equivalent to:
if (rhs.has_value()) convert-ref-init-val(*std::move(rhs));
Remarks: This constructor is defined as deleted if
reference_constructs_from_temporary_v<T&, const U>
is
true. constexpr optional& operator=(nullopt_t) noexcept;
Effects: Assigns
nullptr to
val. Postconditions:
*this does not contain a value
. template<class U>
constexpr T& emplace(U&& u) noexcept(is_nothrow_constructible_v<T&, U>);
Constraints:
- is_constructible_v<T&, U> is true, and
- reference_constructs_from_temporary_v<T&, U> is false.
Effects: Equivalent to:
convert-ref-init-val(std::forward<U>(u)). constexpr void swap(optional& rhs) noexcept;
Effects: Equivalent to:
swap(val, rhs.val). using iterator = implementation-defined;
The reference type is
T& for
iterator. constexpr iterator begin() const noexcept;
Returns: If
has_value() is
true,
an iterator referring to
*val. Otherwise, a past-the-end iterator value
.constexpr iterator end() const noexcept;
Returns:
begin() + has_value(). constexpr T* operator->() const noexcept;
Hardened preconditions:
has_value() is
true. constexpr T& operator*() const noexcept;
Hardened preconditions:
has_value() is
true. constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr T& value() const;
Effects: Equivalent to:
return has_value() ? *val : throw bad_optional_access();
template<class U = remove_cv_t<T>> constexpr remove_cv_t<T> value_or(U&& u) const;
Mandates:
is_constructible_v<X, T&> && is_convertible_v<U, X> is
true. Effects: Equivalent to:
return has_value() ? *val : static_cast<X>(std::forward<U>(u));
template<class F> constexpr auto and_then(F&& f) const;
Let
U be
invoke_result_t<F, T&>.Mandates:
remove_cvref_t<U> is a specialization of
optional. Effects: Equivalent to:
if (has_value()) {
return invoke(std::forward<F>(f), *val);
} else {
return remove_cvref_t<U>();
}
template<class F>
constexpr optional<remove_cv_t<invoke_result_t<F, T&>>> transform(F&& f) const;
Let
U be
remove_cv_t<invoke_result_t<F, T&>>.Mandates: The declaration
U u(invoke(std::forward<F>(f), *val));
is well-formed for some invented variable
u. Returns: If
*this contains a value, an
optional<U> object
whose contained value is direct-non-list-initialized with
invoke(std::forward<F>(f), *val);
otherwise,
optional<U>(). template<class F> constexpr optional or_else(F&& f) const;
Mandates:
is_same_v<remove_cvref_t<invoke_result_t<F>>, optional> is
true. Effects: Equivalent to:
if (has_value()) {
return *val;
} else {
return std::forward<F>(f)();
}
constexpr void reset() noexcept;
Effects: Assigns
nullptr to
val. Postconditions:
*this does not contain a value
. template<class U>
constexpr void convert-ref-init-val(U&& u);
Effects: Creates a variable
r as if by
T& r(std::forward<U>(u));
and then initializes
val with
addressof(r). struct nullopt_t{see below};
inline constexpr nullopt_t nullopt(unspecified);
The struct
nullopt_t is an empty class 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
.Type
nullopt_t shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate
.namespace std {
class bad_optional_access : public exception {
public:
constexpr const char* what() const noexcept override;
};
}
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
.constexpr const char* what() const noexcept override;
Returns: An
implementation-defined
ntbs,
which during constant evaluation is encoded with
the ordinary literal encoding (
[lex.ccon])
. template<class T, class U> constexpr bool operator==(const optional<T>& x, const optional<U>& y);
Constraints: The expression
*x == *y is well-formed and
its result is convertible to
bool. Returns: If
x.has_value() != y.has_value(),
false; otherwise if
x.has_value() == false,
true; otherwise
*x == *y. Remarks: Specializations of this function template
for which
*x == *y is a core constant expression
are constexpr functions
. template<class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<U>& y);
Constraints: The expression
*x != *y is well-formed and
its result is convertible to
bool. Returns: If
x.has_value() != y.has_value(),
true;
otherwise, if
x.has_value() == false,
false;
otherwise
*x != *y. Remarks: Specializations of this function template
for which
*x != *y is a core constant expression
are constexpr functions
. template<class T, class U> constexpr bool operator<(const optional<T>& x, const optional<U>& y);
Constraints:
*x < *y is well-formed
and its result is convertible to
bool. Returns: If
!y,
false;
otherwise, if
!x,
true;
otherwise
*x < *y. Remarks: Specializations of this function template
for which
*x < *y is a core constant expression
are constexpr functions
. template<class T, class U> constexpr bool operator>(const optional<T>& x, const optional<U>& y);
Constraints: The expression
*x > *y is well-formed and
its result is convertible to
bool. Returns: If
!x,
false;
otherwise, if
!y,
true;
otherwise
*x > *y. Remarks: Specializations of this function template
for which
*x > *y is a core constant expression
are constexpr functions
. template<class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<U>& y);
Constraints: The expression
*x <= *y is well-formed and
its result is convertible to
bool. Returns: If
!x,
true;
otherwise, if
!y,
false;
otherwise
*x <= *y. Remarks: Specializations of this function template
for which
*x <= *y is a core constant expression
are constexpr functions
. template<class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<U>& y);
Constraints: The expression
*x >= *y is well-formed and
its result is convertible to
bool. Returns: If
!y,
true;
otherwise, if
!x,
false;
otherwise
*x >= *y. Remarks: Specializations of this function template
for which
*x >= *y is a core constant expression
are constexpr functions
. template<class T, three_way_comparable_with<T> U>
constexpr compare_three_way_result_t<T, U>
operator<=>(const optional<T>& x, const optional<U>& y);
Returns: If
x && y,
*x <=> *y; otherwise
x.has_value() <=> y.has_value(). Remarks: Specializations of this function template
for which
*x <=> *y is a core constant expression
are constexpr functions
. template<class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept;
template<class T> constexpr strong_ordering operator<=>(const optional<T>& x, nullopt_t) noexcept;
Returns:
x.has_value() <=> false. template<class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);
Constraints:
U is not a specialization of
optional. The expression
*x == v is well-formed and
its result is convertible to
bool. Effects: Equivalent to: return x.has_value() ? *x == v : false;
template<class T, class U> constexpr bool operator==(const T& v, const optional<U>& x);
Constraints:
T is not a specialization of
optional. The expression
v == *x is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? v == *x : false;
template<class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);
Constraints:
U is not a specialization of
optional. The expression
*x != v is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? *x != v : true;
template<class T, class U> constexpr bool operator!=(const T& v, const optional<U>& x);
Constraints:
T is not a specialization of
optional. The expression
v != *x is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? v != *x : true;
template<class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);
Constraints:
U is not a specialization of
optional. The expression
*x < v is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? *x < v : true;
template<class T, class U> constexpr bool operator<(const T& v, const optional<U>& x);
Constraints:
T is not a specialization of
optional. The expression
v < *x is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? v < *x : false;
template<class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);
Constraints:
U is not a specialization of
optional. The expression
*x > v is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? *x > v : false;
template<class T, class U> constexpr bool operator>(const T& v, const optional<U>& x);
Constraints:
T is not a specialization of
optional. The expression
v > *x is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? v > *x : true;
template<class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);
Constraints:
U is not a specialization of
optional. The expression
*x <= v is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? *x <= v : true;
template<class T, class U> constexpr bool operator<=(const T& v, const optional<U>& x);
Constraints:
T is not a specialization of
optional. The expression
v <= *x is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? v <= *x : false;
template<class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);
Constraints:
U is not a specialization of
optional. The expression
*x >= v is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? *x >= v : false;
template<class T, class U> constexpr bool operator>=(const T& v, const optional<U>& x);
Constraints:
T is not a specialization of
optional. The expression
v >= *x is well-formed and
its result is convertible to
bool.Effects: Equivalent to: return x.has_value() ? v >= *x : true;
Effects: Equivalent to: return x.has_value() ? *x <=> v : strong_ordering::less;
template<class T>
constexpr void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));
Constraints:
is_reference_v<T> || (is_move_constructible_v<T> && is_swappable_v<T>)
is
true. Effects: Calls
x.swap(y). template<class T> constexpr optional<decay_t<T>> make_optional(T&& v);
Returns:
optional<decay_t<T>>(std::forward<T>(v)). template<class T, class...Args>
constexpr optional<T> make_optional(Args&&... args);
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);
Effects: Equivalent to: return optional<T>(in_place, il, std::forward<Args>(args)...);
template<class T> struct hash<optional<T>>;
The specialization
hash<optional<T>> is enabled (
[unord.hash])
if and only if
hash<remove_const_t<T>> is enabled
. When enabled, for an object
o of type
optional<T>,
if
o.has_value() == true, then
hash<optional<T>>()(o)
evaluates to the same value as
hash<remove_const_t<T>>()(*o);
otherwise it evaluates to an unspecified value
. The member functions are not guaranteed to be
noexcept.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
.
#include <compare>
namespace std {
template<class... Types>
class variant;
template<class T> struct variant_size;
template<class T> struct variant_size<const T>;
template<class T>
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;
template<size_t I, class T> struct variant_alternative<I, const 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;
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...>&&);
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;
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...>&);
template<class... Types> requires (three_way_comparable<Types> && ...)
constexpr common_comparison_category_t<compare_three_way_result_t<Types>...>
operator<=>(const variant<Types...>&, const variant<Types...>&);
template<class Visitor, class... Variants>
constexpr see below visit(Visitor&&, Variants&&...);
template<class R, class Visitor, class... Variants>
constexpr R visit(Visitor&&, Variants&&...);
struct monostate;
constexpr bool operator==(monostate, monostate) noexcept;
constexpr strong_ordering operator<=>(monostate, monostate) noexcept;
template<class... Types>
constexpr void swap(variant<Types...>&, variant<Types...>&) noexcept(see below);
class bad_variant_access;
template<class T> struct hash;
template<class... Types> struct hash<variant<Types...>>;
template<> struct hash<monostate>;
}
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.template<class T> struct variant_size;
All specializations of
variant_size meet the
Cpp17UnaryTypeTrait requirements (
[meta.rqmts])
with a base characteristic of
integral_constant<size_t, N> for some
N.template<class T> struct variant_size<const T>;
Let
VS denote
variant_size<T> of the cv-unqualified
type
T. Then each specialization of the template meets the
Cpp17UnaryTypeTrait requirements (
[meta.rqmts]) 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> struct variant_alternative<I, const T>;
Let
VA denote
variant_alternative<I, T> of the
cv-unqualified type
T. variant_alternative<I, variant<Types...>>::type
Mandates:
I < sizeof...(Types). template<class T, class... Types>
constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
Mandates: The type
T occurs exactly once in
Types. 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);
Mandates:
I < sizeof...(Types). Preconditions:
v.index() is
I. Returns: A reference to the object stored in the
variant. template<size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v);
template<size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v);
template<size_t I, class... Types>
constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v);
template<size_t I, class... Types>
constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v);
Mandates:
I < sizeof...(Types). 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);
Mandates: The type
T occurs exactly once in
Types. 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;
Mandates:
I < sizeof...(Types). 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;
Mandates: The type
T occurs exactly once in
Types. Effects: Equivalent to:
return get_if<i>(v); with
i being the zero-based
index of
T in
Types. template<class... Types>
constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
Constraints:
GET<i>(v) == GET<i>(w) is a valid expression that is
convertible to
bool, for all
i. Returns: If
v.index() != w.index(),
false;
otherwise if
v.valueless_by_exception(),
true;
otherwise
GET<i>(v) == GET<i>(w) with
i being
v.index(). template<class... Types>
constexpr bool operator!=(const variant<Types...>& v, const variant<Types...>& w);
Constraints:
GET<i>(v) != GET<i>(w) is a valid expression that is
convertible to
bool, for all
i. Returns: If
v.index() != w.index(),
true;
otherwise if
v.valueless_by_exception(),
false;
otherwise
GET<i>(v) != GET<i>(w) with
i being
v.index(). template<class... Types>
constexpr bool operator<(const variant<Types...>& v, const variant<Types...>& w);
Constraints:
GET<i>(v) < GET<i>(w) is a valid expression that is
convertible to
bool, for all
i. 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);
Constraints:
GET<i>(v) > GET<i>(w) is a valid expression that is
convertible to
bool, for all
i. 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);
Constraints:
GET<i>(v) <= GET<i>(w) is a valid expression that is
convertible to
bool, for all
i. 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);
Constraints:
GET<i>(v) >= GET<i>(w) is a valid expression that is
convertible to
bool, for all
i. 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(). template<class... Types> requires (three_way_comparable<Types> && ...)
constexpr common_comparison_category_t<compare_three_way_result_t<Types>...>
operator<=>(const variant<Types...>& v, const variant<Types...>& w);
Effects: Equivalent to:
if (v.valueless_by_exception() && w.valueless_by_exception())
return strong_ordering::equal;
if (v.valueless_by_exception()) return strong_ordering::less;
if (w.valueless_by_exception()) return strong_ordering::greater;
if (auto c = v.index() <=> w.index(); c != 0) return c;
return GET<i>(v) <=> GET<i>(w);
with
i being
v.index(). template<class Visitor, class... Variants>
constexpr see below visit(Visitor&& vis, Variants&&... vars);
template<class R, class Visitor, class... Variants>
constexpr R visit(Visitor&& vis, Variants&&... vars);
Let as-variant denote the following exposition-only function templates:
template<class... Ts>
constexpr auto&& as-variant(variant<Ts...>& var) { return var; }
template<class... Ts>
constexpr auto&& as-variant(const variant<Ts...>& var) { return var; }
template<class... Ts>
constexpr auto&& as-variant(variant<Ts...>&& var) { return std::move(var); }
template<class... Ts>
constexpr auto&& as-variant(const variant<Ts...>&& var) { return std::move(var); }
Let
n be
sizeof...(Variants). For each
0≤i<n, let
Vi denote the type
decltype(as-variant(std::forward<Variantsi>(varsi))).Constraints:
Vi is a valid type for all
0≤i<n. Let
V denote the pack of types
Vi.Let
m be a pack of
n values of type
size_t. Such a pack is valid if
0≤mi<variant_size_v<remove_reference_t<Vi>>
for all
0≤i<n. For each valid pack
m, let
e(m) denote the expression:
INVOKE(std::forward<Visitor>(vis), GET<m>(std::forward<V>(vars))...)
for the first form and
INVOKE<R>(std::forward<Visitor>(vis), GET<m>(std::forward<V>(vars))...)
for the second form
.Mandates: For each valid pack
m,
e(m) is a valid expression
. All such expressions are of the same type and value category
.Returns:
e(m), where
m is the pack for which
mi is
as-variant(varsi).index() for all
0≤i<n. The return type is
decltype(e(m))
for the first form
.Throws:
bad_variant_access if
(as-variant(vars).valueless_by_exception() || ...)
is
true. Complexity: For
n ≤ 1, the invocation of the callable object is
implemented in constant time, i.e., for
n=1, it does not depend on
the number of alternative types of
V0. For
n>1, the invocation of the callable object has
no complexity requirements
.template<class Self, class Visitor>
constexpr decltype(auto) visit(this Self&& self, Visitor&& vis);
Let
V be
OVERRIDE_REF(Self&&, COPY_CONST(remove_reference_t<Self>, variant)) (
[forward])
.Effects: Equivalent to: return std::visit(std::forward<Visitor>(vis), (V)self);
template<class R, class Self, class Visitor>
constexpr R visit(this Self&& self, Visitor&& vis);
Let
V be
OVERRIDE_REF(Self&&, COPY_CONST(remove_reference_t<Self>, variant)) (
[forward])
.Effects: Equivalent to: return std::visit<R>(std::forward<Visitor>(vis), (V)self);
The class
monostate can serve as a first alternative type for
a
variant to make the
variant type default constructible
.constexpr bool operator==(monostate, monostate) noexcept { return true; }
constexpr strong_ordering operator<=>(monostate, monostate) noexcept
{ return strong_ordering::equal; }
[
Note 1:
monostate objects have only a single state; they thus always compare equal
. —
end note]
template<class... Types>
constexpr void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below);
Constraints:
is_move_constructible_v<Ti> && is_swappable_v<Ti>
is
true for all
i. Effects: Equivalent to
v.swap(w). Remarks: The exception specification is equivalent to
noexcept(v.swap(w)).
namespace std {
class bad_variant_access : public exception {
public:
constexpr const char* what() const noexcept override;
};
}
Objects of type
bad_variant_access are thrown to report invalid
accesses to the value of a
variant object
.constexpr const char* what() const noexcept override;
Returns: An
implementation-defined
ntbs,
which during constant evaluation is encoded with
the ordinary literal encoding (
[lex.ccon])
. template<class... Types> struct hash<variant<Types...>>;
The specialization
hash<variant<Types...>> is enabled (
[unord.hash])
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>;
Subclause
[any] describes components that C++ programs may use to perform operations on objects of a discriminated type
.[
Note 1:
The discriminated type can 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]
namespace std {
class bad_any_cast;
class any;
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;
}
namespace std {
class bad_any_cast : public bad_cast {
public:
const char* what() const noexcept override;
};
}
Objects of type
bad_any_cast are thrown by a failed
any_cast.const char* what() const noexcept override;
Returns: An
implementation-defined
ntbs. namespace std {
class any {
public:
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();
any& operator=(const any& rhs);
any& operator=(any&& rhs) noexcept;
template<class T>
any& operator=(T&& rhs);
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;
bool has_value() const noexcept;
const type_info& type() const noexcept;
};
}
An object of class
any stores an instance of any type that meets the constructor requirements or it has no value,
and this is referred to as the
state of the class
any object
. Two states are equivalent if either they both have no value, or they both have a value and the contained values are equivalent
.The non-member
any_cast functions provide type-safe access to the contained value
.Implementations should avoid the use of dynamically allocated memory for a small contained value
. However, any such small-object optimization shall only be applied to types
T for which
is_nothrow_move_constructible_v<T> is
true. [
Example 1:
A contained value of type
int could be stored in an internal buffer,
not in separately-allocated memory
. —
end example]
constexpr any() noexcept;
Postconditions:
has_value() is
false. 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
.Throws: Any exceptions arising from calling the selected constructor for the contained value
. any(any&& other) noexcept;
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
.template<class T>
any(T&& value);
Constraints:
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. Effects: Constructs an object of type
any that contains an object of type
VT direct-initialized with
std::forward<T>(value). Throws: Any exception thrown by the selected constructor of
VT. template<class T, class... Args>
explicit any(in_place_type_t<T>, Args&&... args);
Constraints:
is_copy_constructible_v<VT> is
true and
is_constructible_v<VT, Args...> is
true. Effects: Direct-non-list-initializes the contained value of type
VT
with
std::forward<Args>(args).... Postconditions:
*this contains a value of type
VT. Throws: Any exception thrown by the selected constructor of
VT. template<class T, class U, class... Args>
explicit any(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Constraints:
is_copy_constructible_v<VT> is
true and
is_constructible_v<VT, initializer_list<U>&, Args...> is
true. Effects: Direct-non-list-initializes the contained value of type
VT
with
il, std::forward<Args>(args).... Postconditions:
*this contains a value
. Throws: Any exception thrown by the selected constructor of
VT. Effects: As if by
reset(). any& operator=(const any& rhs);
Effects: As if by
any(rhs).swap(*this). No effects if an exception is thrown
.Throws: Any exceptions arising from the copy constructor for the contained value
. any& operator=(any&& rhs) noexcept;
Effects: As if by
any(std::move(rhs)).swap(*this). Postconditions: The state of
*this is equivalent to the original state of
rhs. template<class T>
any& operator=(T&& rhs);
Constraints:
VT is not the same type as
any and
is_copy_constructible_v<VT> is
true. 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
.Throws: Any exception thrown by the selected constructor of
VT. template<class T, class... Args>
decay_t<T>& emplace(Args&&... args);
Constraints:
is_copy_constructible_v<VT> is
true and
is_constructible_v<VT, Args...> is
true. Then direct-non-list-initializes the contained value of type
VT
with
std::forward<Args>(args).... Postconditions:
*this contains a value
. Returns: A reference to the new contained value
. Throws: Any exception thrown by the selected constructor of
VT. Remarks: If an exception is thrown during the call to
VT's constructor,
*this does not contain a value, and any previously contained value
has been destroyed
. template<class T, class U, class... Args>
decay_t<T>& emplace(initializer_list<U> il, Args&&... args);
Constraints:
is_copy_constructible_v<VT> is
true and
is_constructible_v<VT, initializer_list<U>&, Args...> is
true. Then direct-non-list-initializes the contained value
of type
VT with
il, std::forward<Args>(args).... Postconditions:
*this contains a value
. Returns: A reference to the new contained value
. Throws: Any exception thrown by the selected constructor of
VT. Remarks: If an exception is thrown during the call to
VT's constructor,
*this does not contain a value, and any previously contained value
has been destroyed
. Effects: If
has_value() is
true, destroys the contained value
. Postconditions:
has_value() is
false. void swap(any& rhs) noexcept;
Effects: Exchanges the states of
*this and
rhs. bool has_value() const noexcept;
Returns:
true if
*this contains an object, otherwise
false. const type_info& type() const noexcept;
Returns:
typeid(T) if
*this has a contained value of type
T,
otherwise
typeid(void). [
Note 1:
Useful for querying against types known either at compile time or only at runtime
. —
end note]
void swap(any& x, any& y) noexcept;
Effects: Equivalent to
x.swap(y). template<class T, class... Args>
any make_any(Args&&... args);
Effects: Equivalent to: return any(in_place_type<T>, std::forward<Args>(args)...);
template<class T, class U, class... Args>
any make_any(initializer_list<U> il, Args&&... args);
Effects: Equivalent to: return any(in_place_type<T>, il, std::forward<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);
Let
U be the type
remove_cvref_t<T>.Mandates: For the first overload,
is_constructible_v<T, const U&> is
true. For the second overload,
is_constructible_v<T, U&> is
true. For the third overload,
is_constructible_v<T, U> is
true.Returns: For the first and second overload,
static_cast<T>(*any_cast<U>(&operand)). For the third overload,
static_cast<T>(std::move(*any_cast<U>(&operand))).Throws:
bad_any_cast if
operand.type() != typeid(remove_reference_t<T>). [
Example 1:
any x(5);
assert(any_cast<int>(x) == 5);
any_cast<int&>(x) = 10;
assert(any_cast<int>(x) == 10);
x = "Meow";
assert(strcmp(any_cast<const char*>(x), "Meow") == 0);
any_cast<const char*&>(x) = "Harry";
assert(strcmp(any_cast<const char*>(x), "Harry") == 0);
x = string("Meow");
string s, s2("Jane");
s = move(any_cast<string&>(x));
assert(s == "Meow");
any_cast<string&>(x) = move(s2);
assert(any_cast<const string&>(x) == "Jane");
string cat("Meow");
const any y(cat);
assert(any_cast<const string&>(y) == cat);
any_cast<string&>(y);
—
end example]
template<class T>
const T* any_cast(const any* operand) noexcept;
template<class T>
T* any_cast(any* operand) noexcept;
Mandates:
is_void_v<T> is
false. Returns: If
operand != nullptr && operand->type() == typeid(T) is
true,
a pointer to the object contained by
operand;
otherwise,
nullptr. [
Example 2:
bool is_string(const any& operand) {
return any_cast<string>(&operand) != nullptr;
}
—
end example]
Subclause
[expected] describes the class template
expected
that represents expected objects
. An
expected<T, E> object holds
an object of type
T or an object of type
E and
manages the lifetime of the contained objects
.
Subclause
[expected.unexpected] describes the class template
unexpected
that represents unexpected objects stored in
expected objects
.namespace std {
template<class E>
class unexpected {
public:
constexpr unexpected(const unexpected&) = default;
constexpr unexpected(unexpected&&) = default;
template<class Err = E>
constexpr explicit unexpected(Err&&);
template<class... Args>
constexpr explicit unexpected(in_place_t, Args&&...);
template<class U, class... Args>
constexpr explicit unexpected(in_place_t, initializer_list<U>, Args&&...);
constexpr unexpected& operator=(const unexpected&) = default;
constexpr unexpected& operator=(unexpected&&) = default;
constexpr const E& error() const & noexcept;
constexpr E& error() & noexcept;
constexpr const E&& error() const && noexcept;
constexpr E&& error() && noexcept;
constexpr void swap(unexpected& other) noexcept(see below);
template<class E2>
friend constexpr bool operator==(const unexpected&, const unexpected<E2>&);
friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y)));
private:
E unex;
};
template<class E> unexpected(E) -> unexpected<E>;
}
A program that instantiates the definition of
unexpected for
a non-object type,
an array type,
a specialization of
unexpected, or
a cv-qualified type
is ill-formed
.template<class Err = E>
constexpr explicit unexpected(Err&& e);
Constraints:
- is_same_v<remove_cvref_t<Err>, unexpected> is false; and
- is_same_v<remove_cvref_t<Err>, in_place_t> is false; and
- is_constructible_v<E, Err> is true.
Effects: Direct-non-list-initializes
unex with
std::forward<Err>(e). Throws: Any exception thrown by the initialization of
unex. template<class... Args>
constexpr explicit unexpected(in_place_t, Args&&... args);
Constraints:
is_constructible_v<E, Args...> is
true. Effects: Direct-non-list-initializes
unex with
std::forward<Args>(args).... Throws: Any exception thrown by the initialization of
unex. template<class U, class... Args>
constexpr explicit unexpected(in_place_t, initializer_list<U> il, Args&&... args);
Constraints:
is_constructible_v<E, initializer_list<U>&, Args...> is
true. Effects: Direct-non-list-initializes
unex with
il, std::forward<Args>(args).... Throws: Any exception thrown by the initialization of
unex. constexpr const E& error() const & noexcept;
constexpr E& error() & noexcept;
constexpr E&& error() && noexcept;
constexpr const E&& error() const && noexcept;
Returns:
std::move(unex). constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v<E>);
Mandates:
is_swappable_v<E> is
true. Effects: Equivalent to:
using std::swap; swap(unex, other.unex);
friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y)));
Constraints:
is_swappable_v<E> is
true. Effects: Equivalent to
x.swap(y). template<class E2>
friend constexpr bool operator==(const unexpected& x, const unexpected<E2>& y);
Mandates: The expression
x.error() == y.error() is well-formed and
its result is convertible to
bool. Returns:
x.error() == y.error(). namespace std {
template<class E>
class bad_expected_access : public bad_expected_access<void> {
public:
constexpr explicit bad_expected_access(E);
constexpr const char* what() const noexcept override;
constexpr E& error() & noexcept;
constexpr const E& error() const & noexcept;
constexpr E&& error() && noexcept;
constexpr const E&& error() const && noexcept;
private:
E unex;
};
}
The class template
bad_expected_access
defines the type of objects thrown as exceptions to report the situation
where an attempt is made to access the value of an
expected<T, E> object
for which
has_value() is
false.constexpr explicit bad_expected_access(E e);
Effects: Initializes
unex with
std::move(e). constexpr const E& error() const & noexcept;
constexpr E& error() & noexcept;
constexpr E&& error() && noexcept;
constexpr const E&& error() const && noexcept;
Returns:
std::move(unex). constexpr const char* what() const noexcept override;
Returns: An
implementation-defined
ntbs,
which during constant evaluation is encoded with
the ordinary literal encoding (
[lex.ccon])
. namespace std {
template<>
class bad_expected_access<void> : public exception {
protected:
constexpr bad_expected_access() noexcept;
constexpr bad_expected_access(const bad_expected_access&) noexcept;
constexpr bad_expected_access(bad_expected_access&&) noexcept;
constexpr bad_expected_access& operator=(const bad_expected_access&) noexcept;
constexpr bad_expected_access& operator=(bad_expected_access&&) noexcept;
constexpr ~bad_expected_access();
public:
constexpr const char* what() const noexcept override;
};
}
constexpr const char* what() const noexcept override;
Returns: An
implementation-defined
ntbs,
which during constant evaluation is encoded with
the ordinary literal encoding (
[lex.ccon])
. namespace std {
template<class T, class E>
class expected {
public:
using value_type = T;
using error_type = E;
using unexpected_type = unexpected<E>;
template<class U>
using rebind = expected<U, error_type>;
constexpr expected();
constexpr expected(const expected&);
constexpr expected(expected&&) noexcept(see below);
template<class U, class G>
constexpr explicit(see below) expected(const expected<U, G>&);
template<class U, class G>
constexpr explicit(see below) expected(expected<U, G>&&);
template<class U = remove_cv_t<T>>
constexpr explicit(see below) expected(U&& v);
template<class G>
constexpr explicit(see below) expected(const unexpected<G>&);
template<class G>
constexpr explicit(see below) expected(unexpected<G>&&);
template<class... Args>
constexpr explicit expected(in_place_t, Args&&...);
template<class U, class... Args>
constexpr explicit expected(in_place_t, initializer_list<U>, Args&&...);
template<class... Args>
constexpr explicit expected(unexpect_t, Args&&...);
template<class U, class... Args>
constexpr explicit expected(unexpect_t, initializer_list<U>, Args&&...);
constexpr ~expected();
constexpr expected& operator=(const expected&);
constexpr expected& operator=(expected&&) noexcept(see below);
template<class U = remove_cv_t<T>> constexpr expected& operator=(U&&);
template<class G>
constexpr expected& operator=(const unexpected<G>&);
template<class G>
constexpr expected& operator=(unexpected<G>&&);
template<class... Args>
constexpr T& emplace(Args&&...) noexcept;
template<class U, class... Args>
constexpr T& emplace(initializer_list<U>, Args&&...) noexcept;
constexpr void swap(expected&) noexcept(see below);
friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
constexpr const T* operator->() const noexcept;
constexpr T* operator->() noexcept;
constexpr const T& operator*() const & noexcept;
constexpr T& operator*() & noexcept;
constexpr const T&& operator*() const && noexcept;
constexpr T&& operator*() && noexcept;
constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr const T& value() const &;
constexpr T& value() &;
constexpr const T&& value() const &&;
constexpr T&& value() &&;
constexpr const E& error() const & noexcept;
constexpr E& error() & noexcept;
constexpr const E&& error() const && noexcept;
constexpr E&& error() && noexcept;
template<class U = remove_cv_t<T>> constexpr T value_or(U&&) const &;
template<class U = remove_cv_t<T>> constexpr T value_or(U&&) &&;
template<class G = E> constexpr E error_or(G&&) const &;
template<class G = E> constexpr E error_or(G&&) &&;
template<class F> constexpr auto and_then(F&& f) &;
template<class F> constexpr auto and_then(F&& f) &&;
template<class F> constexpr auto and_then(F&& f) const &;
template<class F> constexpr auto and_then(F&& f) const &&;
template<class F> constexpr auto or_else(F&& f) &;
template<class F> constexpr auto or_else(F&& f) &&;
template<class F> constexpr auto or_else(F&& f) const &;
template<class F> constexpr auto or_else(F&& f) const &&;
template<class F> constexpr auto transform(F&& f) &;
template<class F> constexpr auto transform(F&& f) &&;
template<class F> constexpr auto transform(F&& f) const &;
template<class F> constexpr auto transform(F&& f) const &&;
template<class F> constexpr auto transform_error(F&& f) &;
template<class F> constexpr auto transform_error(F&& f) &&;
template<class F> constexpr auto transform_error(F&& f) const &;
template<class F> constexpr auto transform_error(F&& f) const &&;
template<class T2, class E2> requires (!is_void_v<T2>)
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
template<class T2>
friend constexpr bool operator==(const expected&, const T2&);
template<class E2>
friend constexpr bool operator==(const expected&, const unexpected<E2>&);
private:
bool has_val;
union {
T val;
E unex;
};
};
}
Any object of type
expected<T, E> either
contains a value of type
T or
a value of type
E
nested within (
[intro.object]) it
. Member
has_val indicates whether the
expected<T, E> object
contains an object of type
T.A type
T is a
valid value type for expected,
if
remove_cv_t<T> is
void
or a complete non-array object type that is not
in_place_t,
unexpect_t,
or a specialization of
unexpected. A program which instantiates class template
expected<T, E>
with an argument
T that is not a valid value
type for
expected is ill-formed
. A program that instantiates
the definition of the template
expected<T, E>
with a type for the
E parameter
that is not a valid template argument for
unexpected is ill-formed
.The exposition-only variable template
converts-from-any-cvref
defined in
[optional.ctor]
is used by some constructors for
expected.Constraints:
is_default_constructible_v<T> is
true. Effects: Value-initializes
val. Postconditions:
has_value() is
true. Throws: Any exception thrown by the initialization of
val. constexpr expected(const expected& rhs);
Effects: If
rhs.has_value() is
true,
direct-non-list-initializes
val with
*rhs. Otherwise, direct-non-list-initializes
unex with
rhs.error().Postconditions:
rhs.has_value() == this->has_value(). Throws: Any exception thrown by the initialization of
val or
unex. Remarks: This constructor is defined as deleted unless
- is_copy_constructible_v<T> is true and
- is_copy_constructible_v<E> is true.
This constructor is trivial if
- is_trivially_copy_constructible_v<T> is true and
- is_trivially_copy_constructible_v<E> is true.
constexpr expected(expected&& rhs) noexcept(see below);
Constraints:
- is_move_constructible_v<T> is true and
- is_move_constructible_v<E> is true.
Effects: If
rhs.has_value() is
true,
direct-non-list-initializes
val with
std::move(*rhs). Otherwise,
direct-non-list-initializes
unex with
std::move(rhs.error()).Postconditions:
rhs.has_value() is unchanged;
rhs.has_value() == this->has_value() is
true. Throws: Any exception thrown by the initialization of
val or
unex. Remarks: The exception specification is equivalent to
is_nothrow_move_constructible_v<T> &&
is_nothrow_move_constructible_v<E>. This constructor is trivial if
- is_trivially_move_constructible_v<T> is true and
- is_trivially_move_constructible_v<E> is true.
template<class U, class G>
constexpr explicit(see below) expected(const expected<U, G>& rhs);
template<class U, class G>
constexpr explicit(see below) expected(expected<U, G>&& rhs);
Let:
UF be
const U& for the first overload and
U for the second overload
. GF be
const G& for the first overload and
G for the second overload
.
Constraints:
- is_constructible_v<T, UF> is true; and
- is_constructible_v<E, GF> is true; and
- if T is not cv bool,
converts-from-any-cvref<T, expected<U, G>> is false; and
- is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
- is_constructible_v<unexpected<E>, expected<U, G>> is false; and
- is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
- is_constructible_v<unexpected<E>, const expected<U, G>> is false.
Effects: If
rhs.has_value(),
direct-non-list-initializes
val with
std::forward<UF>(*rhs). Otherwise,
direct-non-list-initializes
unex with
std::forward<GF>(rhs.error()).Postconditions:
rhs.has_value() is unchanged;
rhs.has_value() == this->has_value() is
true. Throws: Any exception thrown by the initialization of
val or
unex. Remarks: The expression inside
explicit is equivalent to
!is_convertible_v<UF, T> || !is_convertible_v<GF, E>. template<class U = remove_cv_t<T>>
constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);
Constraints:
- is_same_v<remove_cvref_t<U>, in_place_t> is false; and
- is_same_v<remove_cvref_t<U>, expected> is false; and
- is_same_v<remove_cvref_t<U>, unexpect_t> is false; and
- remove_cvref_t<U> is not a specialization of unexpected; and
- is_constructible_v<T, U> is true; and
- if T is cv bool,
remove_cvref_t<U> is not a specialization of expected.
Effects: Direct-non-list-initializes
val with
std::forward<U>(v). Postconditions:
has_value() is
true. Throws: Any exception thrown by the initialization of
val. template<class G>
constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e);
template<class G>
constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
Let
GF be
const G& for the first overload and
G for the second overload
.Constraints:
is_constructible_v<E, GF> is
true. Effects: Direct-non-list-initializes
unex with
std::forward<GF>(e.error()). Postconditions:
has_value() is
false. Throws: Any exception thrown by the initialization of
unex. template<class... Args>
constexpr explicit expected(in_place_t, Args&&... args);
Constraints:
is_constructible_v<T, Args...> is
true. Effects: Direct-non-list-initializes
val with
std::forward<Args>(args).... Postconditions:
has_value() is
true. Throws: Any exception thrown by the initialization of
val. template<class U, class... Args>
constexpr explicit expected(in_place_t, initializer_list<U> il, Args&&... args);
Constraints:
is_constructible_v<T, initializer_list<U>&, Args...> is
true. Effects: Direct-non-list-initializes
val with
il, std::forward<Args>(args).... Postconditions:
has_value() is
true. Throws: Any exception thrown by the initialization of
val. template<class... Args>
constexpr explicit expected(unexpect_t, Args&&... args);
Constraints:
is_constructible_v<E, Args...> is
true. Effects: Direct-non-list-initializes
unex with
std::forward<Args>(args).... Postconditions:
has_value() is
false. Throws: Any exception thrown by the initialization of
unex. template<class U, class... Args>
constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
Constraints:
is_constructible_v<E, initializer_list<U>&, Args...> is
true. Effects: Direct-non-list-initializes
unex with
il, std::forward<Args>(args).... Postconditions:
has_value() is
false. Throws: Any exception thrown by the initialization of
unex. Effects: If
has_value() is
true, destroys
val,
otherwise destroys
unex. Remarks: If
is_trivially_destructible_v<T> is
true, and
is_trivially_destructible_v<E> is
true,
then this destructor is a trivial destructor
. This subclause makes use of the following exposition-only function template:
template<class T, class U, class... Args>
constexpr void reinit-expected(T& newval, U& oldval, Args&&... args) {
if constexpr (is_nothrow_constructible_v<T, Args...>) {
destroy_at(addressof(oldval));
construct_at(addressof(newval), std::forward<Args>(args)...);
} else if constexpr (is_nothrow_move_constructible_v<T>) {
T tmp(std::forward<Args>(args)...);
destroy_at(addressof(oldval));
construct_at(addressof(newval), std::move(tmp));
} else {
U tmp(std::move(oldval));
destroy_at(addressof(oldval));
try {
construct_at(addressof(newval), std::forward<Args>(args)...);
} catch (...) {
construct_at(addressof(oldval), std::move(tmp));
throw;
}
}
}
constexpr expected& operator=(const expected& rhs);
Effects:
If
this->has_value() && rhs.has_value() is
true,
equivalent to
val = *rhs.Otherwise, if this->has_value() is true, equivalent to:
reinit-expected(unex, val, rhs.error())
Otherwise, if rhs.has_value() is true, equivalent to:
reinit-expected(val, unex, *rhs)
Otherwise, equivalent to
unex = rhs.error().
Then, if no exception was thrown,
equivalent to: has_val = rhs.has_value(); return *this;
Remarks: This operator is defined as deleted unless:
- is_copy_assignable_v<T> is true and
- is_copy_constructible_v<T> is true and
- is_copy_assignable_v<E> is true and
- is_copy_constructible_v<E> is true and
- is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E>
is true.
constexpr expected& operator=(expected&& rhs) noexcept(see below);
Constraints:
- is_move_constructible_v<T> is true and
- is_move_assignable_v<T> is true and
- is_move_constructible_v<E> is true and
- is_move_assignable_v<E> is true and
- is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E>
is true.
Effects:
If
this->has_value() && rhs.has_value() is
true,
equivalent to
val = std::move(*rhs).Otherwise, if this->has_value() is true, equivalent to:
reinit-expected(unex, val, std::move(rhs.error()))
Otherwise, if rhs.has_value() is true, equivalent to:
reinit-expected(val, unex, std::move(*rhs))
Otherwise, equivalent to
unex = std::move(rhs.error()).
Then, if no exception was thrown,
equivalent to: has_val = rhs.has_value(); return *this;
Remarks: The exception specification is equivalent to:
is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> &&
is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
template<class U = remove_cv_t<T>>
constexpr expected& operator=(U&& v);
Constraints:
- is_same_v<expected, remove_cvref_t<U>> is false; and
- remove_cvref_t<U> is not a specialization of unexpected; and
- is_constructible_v<T, U> is true; and
- is_assignable_v<T&, U> is true; and
- is_nothrow_constructible_v<T, U> || is_nothrow_move_constructible_v<T> ||
is_nothrow_move_constructible_v<E>
is true.
Effects:
- If has_value() is true,
equivalent to: val = std::forward<U>(v);
- Otherwise, equivalent to:
reinit-expected(val, unex, std::forward<U>(v));
has_val = true;
template<class G>
constexpr expected& operator=(const unexpected<G>& e);
template<class G>
constexpr expected& operator=(unexpected<G>&& e);
Let
GF be
const G& for the first overload and
G for the second overload
.Constraints:
- is_constructible_v<E, GF> is true; and
- is_assignable_v<E&, GF> is true; and
- is_nothrow_constructible_v<E, GF> || is_nothrow_move_constructible_v<T> ||
is_nothrow_move_constructible_v<E> is true.
Effects:
- If has_value() is true, equivalent to:
reinit-expected(unex, val, std::forward<GF>(e.error()));
has_val = false;
- Otherwise, equivalent to:
unex = std::forward<GF>(e.error());
template<class... Args>
constexpr T& emplace(Args&&... args) noexcept;
Constraints:
is_nothrow_constructible_v<T, Args...> is
true. Effects: Equivalent to:
if (has_value()) {
destroy_at(addressof(val));
} else {
destroy_at(addressof(unex));
has_val = true;
}
return *construct_at(addressof(val), std::forward<Args>(args)...);
template<class U, class... Args>
constexpr T& emplace(initializer_list<U> il, Args&&... args) noexcept;
Constraints:
is_nothrow_constructible_v<T, initializer_list<U>&, Args...>
is
true. Effects: Equivalent to:
if (has_value()) {
destroy_at(addressof(val));
} else {
destroy_at(addressof(unex));
has_val = true;
}
return *construct_at(addressof(val), il, std::forward<Args>(args)...);
constexpr void swap(expected& rhs) noexcept(see below);
Constraints:
- is_swappable_v<T> is true and
- is_swappable_v<E> is true and
- is_move_constructible_v<T> && is_move_constructible_v<E>
is true, and
- is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E>
is true.
Table
72 —
swap(expected&) effects
[tab:expected.object.swap] | | |
| equivalent to: using std::swap; swap(val, rhs.val); | |
| | equivalent to: using std::swap; swap(unex, rhs.unex); |
For the case where rhs.has_value() is false and
this->has_value() is true, equivalent to:
if constexpr (is_nothrow_move_constructible_v<E>) {
E tmp(std::move(rhs.unex));
destroy_at(addressof(rhs.unex));
try {
construct_at(addressof(rhs.val), std::move(val));
destroy_at(addressof(val));
construct_at(addressof(unex), std::move(tmp));
} catch(...) {
construct_at(addressof(rhs.unex), std::move(tmp));
throw;
}
} else {
T tmp(std::move(val));
destroy_at(addressof(val));
try {
construct_at(addressof(unex), std::move(rhs.unex));
destroy_at(addressof(rhs.unex));
construct_at(addressof(rhs.val), std::move(tmp));
} catch (...) {
construct_at(addressof(val), std::move(tmp));
throw;
}
}
has_val = false;
rhs.has_val = true;
Throws: Any exception thrown by the expressions in the
Effects. Remarks: The exception specification is equivalent to:
is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T> &&
is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>
friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
Effects: Equivalent to
x.swap(y). constexpr const T* operator->() const noexcept;
constexpr T* operator->() noexcept;
Hardened preconditions:
has_value() is
true. constexpr const T& operator*() const & noexcept;
constexpr T& operator*() & noexcept;
Hardened preconditions:
has_value() is
true. constexpr T&& operator*() && noexcept;
constexpr const T&& operator*() const && noexcept;
Hardened preconditions:
has_value() is
true. Returns:
std::move(val). constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr const T& value() const &;
constexpr T& value() &;
Mandates:
is_copy_constructible_v<E> is
true. Returns:
val, if
has_value() is
true. Throws:
bad_expected_access(as_const(error())) if
has_value() is
false. constexpr T&& value() &&;
constexpr const T&& value() const &&;
Mandates:
is_copy_constructible_v<E> is
true and
is_constructible_v<E, decltype(std::move(error()))> is
true. Returns:
std::move(val), if
has_value() is
true. Throws:
bad_expected_access(std::move(error()))
if
has_value() is
false. constexpr const E& error() const & noexcept;
constexpr E& error() & noexcept;
Hardened preconditions:
has_value() is
false. constexpr E&& error() && noexcept;
constexpr const E&& error() const && noexcept;
Hardened preconditions:
has_value() is
false. Returns:
std::move(unex). template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) const &;
Mandates:
is_copy_constructible_v<T> is
true and
is_convertible_v<U, T> is
true. Returns:
has_value() ? **this : static_cast<T>(std::forward<U>(v)). template<class U = remove_cv_t<T>> constexpr T value_or(U&& v) &&;
Mandates:
is_move_constructible_v<T> is
true and
is_convertible_v<U, T> is
true. Returns:
has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v)). template<class G = E> constexpr E error_or(G&& e) const &;
Mandates:
is_copy_constructible_v<E> is
true and
is_convertible_v<G, E> is
true. Returns:
std::forward<G>(e) if
has_value() is
true,
error() otherwise
. template<class G = E> constexpr E error_or(G&& e) &&;
Mandates:
is_move_constructible_v<E> is
true and
is_convertible_v<G, E> is
true. Returns:
std::forward<G>(e) if
has_value() is
true,
std::move(error()) otherwise
. template<class F> constexpr auto and_then(F&& f) &;
template<class F> constexpr auto and_then(F&& f) const &;
Let
U be
remove_cvref_t<invoke_result_t<F, decltype((val))>>.Constraints:
is_constructible_v<E, decltype(error())> is
true. Mandates:
U is a specialization of
expected and
is_same_v<U::error_type, E> is
true. Effects: Equivalent to:
if (has_value())
return invoke(std::forward<F>(f), val);
else
return U(unexpect, error());
template<class F> constexpr auto and_then(F&& f) &&;
template<class F> constexpr auto and_then(F&& f) const &&;
Let
U be
remove_cvref_t<invoke_result_t<F, decltype(std::move(val))>>.Constraints:
is_constructible_v<E, decltype(std::move(error()))> is
true. Mandates:
U is a specialization of
expected and
is_same_v<U::error_type, E> is
true. Effects: Equivalent to:
if (has_value())
return invoke(std::forward<F>(f), std::move(val));
else
return U(unexpect, std::move(error()));
template<class F> constexpr auto or_else(F&& f) &;
template<class F> constexpr auto or_else(F&& f) const &;
Let
G be
remove_cvref_t<invoke_result_t<F, decltype(error())>>.Constraints:
is_constructible_v<T, decltype((val))> is
true. Mandates:
G is a specialization of
expected and
is_same_v<G::value_type, T> is
true. Effects: Equivalent to:
if (has_value())
return G(in_place, val);
else
return invoke(std::forward<F>(f), error());
template<class F> constexpr auto or_else(F&& f) &&;
template<class F> constexpr auto or_else(F&& f) const &&;
Let
G be
remove_cvref_t<invoke_result_t<F, decltype(std::move(error()))>>.Constraints:
is_constructible_v<T, decltype(std::move(val))> is
true. Mandates:
G is a specialization of
expected and
is_same_v<G::value_type, T> is
true. Effects: Equivalent to:
if (has_value())
return G(in_place, std::move(val));
else
return invoke(std::forward<F>(f), std::move(error()));
Let
U be
remove_cv_t<invoke_result_t<F, decltype((val))>>.Constraints:
is_constructible_v<E, decltype(error())> is
true. Mandates:
U is a valid value type for
expected. If
is_void_v<U> is
false,
the declaration
U u(invoke(std::forward<F>(f), val));
is well-formed
.Effects:
If
has_value() is
false, returns
expected<U, E>(unexpect, error()).Otherwise, if
is_void_v<U> is
false, returns an
expected<U, E> object whose
has_val member is
true
and
val member is direct-non-list-initialized with
invoke(std::forward<F>(f), val).Otherwise, evaluates
invoke(std::forward<F>(f), val) and then
returns
expected<U, E>().
Let
U be
remove_cv_t<invoke_result_t<F, decltype(std::move(val))>>.Constraints:
is_constructible_v<E, decltype(std::move(error()))> is
true. Mandates:
U is a valid value type for
expected. If
is_void_v<U> is
false, the declaration
U u(invoke(std::forward<F>(f), std::move(val)));
is well-formed
.Effects:
If
has_value() is
false, returns
expected<U, E>(unexpect, std::move(error())).Otherwise, if
is_void_v<U> is
false, returns an
expected<U, E> object whose
has_val member is
true
and
val member is direct-non-list-initialized with
invoke(std::forward<F>(f), std::move(val)).Otherwise, evaluates
invoke(std::forward<F>(f), std::move(val)) and
then returns
expected<U, E>().
Let
G be
remove_cv_t<invoke_result_t<F, decltype(error())>>.Constraints:
is_constructible_v<T, decltype((val))> is
true. Mandates:
G is a valid template argument
for
unexpected (
[expected.un.general]) and the declaration
G g(invoke(std::forward<F>(f), error()));
is well-formed
. Returns: If
has_value() is
true,
expected<T, G>(in_place, val); otherwise, an
expected<T, G>
object whose
has_val member is
false and
unex member
is direct-non-list-initialized with
invoke(std::forward<F>(f), error()). Let
G be
remove_cv_t<invoke_result_t<F, decltype(std::move(error()))>>.Constraints:
is_constructible_v<T, decltype(std::move(val))> is
true. Mandates:
G is a valid template argument
for
unexpected (
[expected.un.general]) and the declaration
G g(invoke(std::forward<F>(f), std::move(error())));
is well-formed
. Returns: If
has_value() is
true,
expected<T, G>(in_place, std::move(val)); otherwise, an
expected<T, G> object whose
has_val member is
false
and
unex member is direct-non-list-initialized with
invoke(std::forward<F>(f), std::move(error())). template<class T2, class E2> requires (!is_void_v<T2>)
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
Constraints: The expressions
*x == *y and
x.error() == y.error()
are well-formed and their results are convertible to
bool. Returns: If
x.has_value() does not equal
y.has_value(),
false;
otherwise if
x.has_value() is
true,
*x == *y;
otherwise
x.error() == y.error(). template<class T2> friend constexpr bool operator==(const expected& x, const T2& v);
Constraints:
T2 is not a specialization of
expected. The expression
*x == v is well-formed and
its result is convertible to
bool. Returns:
x.has_value() && static_cast<bool>(*x == v). template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
Constraints: The expression
x.error() == e.error() is well-formed and
its result is convertible to
bool. Returns:
!x.has_value() && static_cast<bool>(x.error() == e.error()). template<class T, class E> requires is_void_v<T>
class expected<T, E> {
public:
using value_type = T;
using error_type = E;
using unexpected_type = unexpected<E>;
template<class U>
using rebind = expected<U, error_type>;
constexpr expected() noexcept;
constexpr expected(const expected&);
constexpr expected(expected&&) noexcept(see below);
template<class U, class G>
constexpr explicit(see below) expected(const expected<U, G>&);
template<class U, class G>
constexpr explicit(see below) expected(expected<U, G>&&);
template<class G>
constexpr explicit(see below) expected(const unexpected<G>&);
template<class G>
constexpr explicit(see below) expected(unexpected<G>&&);
constexpr explicit expected(in_place_t) noexcept;
template<class... Args>
constexpr explicit expected(unexpect_t, Args&&...);
template<class U, class... Args>
constexpr explicit expected(unexpect_t, initializer_list<U>, Args&&...);
constexpr ~expected();
constexpr expected& operator=(const expected&);
constexpr expected& operator=(expected&&) noexcept(see below);
template<class G>
constexpr expected& operator=(const unexpected<G>&);
template<class G>
constexpr expected& operator=(unexpected<G>&&);
constexpr void emplace() noexcept;
constexpr void swap(expected&) noexcept(see below);
friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr void operator*() const noexcept;
constexpr void value() const &;
constexpr void value() &&;
constexpr const E& error() const & noexcept;
constexpr E& error() & noexcept;
constexpr const E&& error() const && noexcept;
constexpr E&& error() && noexcept;
template<class G = E> constexpr E error_or(G&&) const &;
template<class G = E> constexpr E error_or(G&&) &&;
template<class F> constexpr auto and_then(F&& f) &;
template<class F> constexpr auto and_then(F&& f) &&;
template<class F> constexpr auto and_then(F&& f) const &;
template<class F> constexpr auto and_then(F&& f) const &&;
template<class F> constexpr auto or_else(F&& f) &;
template<class F> constexpr auto or_else(F&& f) &&;
template<class F> constexpr auto or_else(F&& f) const &;
template<class F> constexpr auto or_else(F&& f) const &&;
template<class F> constexpr auto transform(F&& f) &;
template<class F> constexpr auto transform(F&& f) &&;
template<class F> constexpr auto transform(F&& f) const &;
template<class F> constexpr auto transform(F&& f) const &&;
template<class F> constexpr auto transform_error(F&& f) &;
template<class F> constexpr auto transform_error(F&& f) &&;
template<class F> constexpr auto transform_error(F&& f) const &;
template<class F> constexpr auto transform_error(F&& f) const &&;
template<class T2, class E2> requires is_void_v<T2>
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
template<class E2>
friend constexpr bool operator==(const expected&, const unexpected<E2>&);
private:
bool has_val;
union {
E unex;
};
};
Any object of type
expected<T, E> either
represents a value of type
T, or
contains a value of type
E
nested within (
[intro.object]) it
. Member
has_val indicates whether the
expected<T, E> object
represents a value of type
T.A program that instantiates
the definition of the template
expected<T, E> with
a type for the
E parameter that
is not a valid template argument for
unexpected is ill-formed
.constexpr expected() noexcept;
Postconditions:
has_value() is
true. constexpr expected(const expected& rhs);
Effects: If
rhs.has_value() is
false,
direct-non-list-initializes
unex with
rhs.error(). Postconditions:
rhs.has_value() == this->has_value(). Throws: Any exception thrown by the initialization of
unex. Remarks: This constructor is defined as deleted
unless
is_copy_constructible_v<E> is
true. This constructor is trivial
if
is_trivially_copy_constructible_v<E> is
true.constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v<E>);
Constraints:
is_move_constructible_v<E> is
true. Effects: If
rhs.has_value() is
false,
direct-non-list-initializes
unex with
std::move(rhs.error()). Postconditions:
rhs.has_value() is unchanged;
rhs.has_value() == this->has_value() is
true. Throws: Any exception thrown by the initialization of
unex. Remarks: This constructor is trivial
if
is_trivially_move_constructible_v<E> is
true. template<class U, class G>
constexpr explicit(!is_convertible_v<const G&, E>) expected(const expected<U, G>& rhs);
template<class U, class G>
constexpr explicit(!is_convertible_v<G, E>) expected(expected<U, G>&& rhs);
Let
GF be
const G& for the first overload and
G for the second overload
.Constraints:
- is_void_v<U> is true; and
- is_constructible_v<E, GF> is true; and
- is_constructible_v<unexpected<E>, expected<U, G>&>
is false; and
- is_constructible_v<unexpected<E>, expected<U, G>>
is false; and
- is_constructible_v<unexpected<E>, const expected<U, G>&>
is false; and
- is_constructible_v<unexpected<E>, const expected<U, G>>
is false.
Effects: If
rhs.has_value() is
false,
direct-non-list-initializes
unex
with
std::forward<GF>(rhs.error()). Postconditions:
rhs.has_value() is unchanged;
rhs.has_value() == this->has_value() is
true. Throws: Any exception thrown by the initialization of
unex. template<class G>
constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e);
template<class G>
constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
Let
GF be
const G& for the first overload and
G for the second overload
.Constraints:
is_constructible_v<E, GF> is
true. Effects: Direct-non-list-initializes
unex
with
std::forward<GF>(e.error()). Postconditions:
has_value() is
false. Throws: Any exception thrown by the initialization of
unex. constexpr explicit expected(in_place_t) noexcept;
Postconditions:
has_value() is
true. template<class... Args>
constexpr explicit expected(unexpect_t, Args&&... args);
Constraints:
is_constructible_v<E, Args...> is
true. Effects: Direct-non-list-initializes
unex
with
std::forward<Args>(args).... Postconditions:
has_value() is
false. Throws: Any exception thrown by the initialization of
unex. template<class U, class... Args>
constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
Constraints:
is_constructible_v<E, initializer_list<U>&, Args...> is
true. Effects: Direct-non-list-initializes
unex
with
il, std::forward<Args>(args).... Postconditions:
has_value() is
false. Throws: Any exception thrown by the initialization of
unex. Effects: If
has_value() is
false, destroys
unex. Remarks: If
is_trivially_destructible_v<E> is
true,
then this destructor is a trivial destructor
. constexpr expected& operator=(const expected& rhs);
Effects:
If
this->has_value() && rhs.has_value() is
true, no effects
.Otherwise, if this->has_value() is true,
equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false;
Otherwise, if
rhs.has_value() is
true,
destroys
unex and sets
has_val to
true.Otherwise, equivalent to
unex = rhs.error().
Remarks: This operator is defined as deleted unless
is_copy_assignable_v<E> is
true and
is_copy_constructible_v<E> is
true. constexpr expected& operator=(expected&& rhs) noexcept(see below);
Constraints:
is_move_constructible_v<E> is
true and
is_move_assignable_v<E> is
true. Effects:
If
this->has_value() && rhs.has_value() is
true, no effects
.Otherwise, if this->has_value() is true, equivalent to:
construct_at(addressof(unex), std::move(rhs.unex));
has_val = false;
Otherwise, if
rhs.has_value() is
true,
destroys
unex and sets
has_val to
true.Otherwise, equivalent to
unex = std::move(rhs.error()).
Remarks: The exception specification is equivalent to
is_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>. template<class G>
constexpr expected& operator=(const unexpected<G>& e);
template<class G>
constexpr expected& operator=(unexpected<G>&& e);
Let
GF be
const G& for the first overload and
G for the second overload
.Constraints:
is_constructible_v<E, GF> is
true and
is_assignable_v<E&, GF> is
true. Effects:
- If has_value() is true, equivalent to:
construct_at(addressof(unex), std::forward<GF>(e.error()));
has_val = false;
- Otherwise, equivalent to:
unex = std::forward<GF>(e.error());
constexpr void emplace() noexcept;
Effects: If
has_value() is
false,
destroys
unex and sets
has_val to
true. constexpr void swap(expected& rhs) noexcept(see below);
Constraints:
is_swappable_v<E> is
true and
is_move_constructible_v<E> is
true. For the case where rhs.has_value() is false and
this->has_value() is true, equivalent to:
construct_at(addressof(unex), std::move(rhs.unex));
destroy_at(addressof(rhs.unex));
has_val = false;
rhs.has_val = true;
Throws: Any exception thrown by the expressions in the
Effects. Remarks: The exception specification is equivalent to
is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>. friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
Effects: Equivalent to
x.swap(y). constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr void operator*() const noexcept;
Hardened preconditions:
has_value() is
true. constexpr void value() const &;
Mandates:
is_copy_constructible_v<E> is
true. Throws:
bad_expected_access(error()) if
has_value() is
false. constexpr void value() &&;
Mandates:
is_copy_constructible_v<E> is
true and
is_move_constructible_v<E> is
true. Throws:
bad_expected_access(std::move(error()))
if
has_value() is
false. constexpr const E& error() const & noexcept;
constexpr E& error() & noexcept;
Hardened preconditions:
has_value() is
false. constexpr E&& error() && noexcept;
constexpr const E&& error() const && noexcept;
Hardened preconditions:
has_value() is
false. Returns:
std::move(unex). template<class G = E> constexpr E error_or(G&& e) const &;
Mandates:
is_copy_constructible_v<E> is
true and
is_convertible_v<G, E> is
true. Returns:
std::forward<G>(e) if
has_value() is
true,
error() otherwise
. template<class G = E> constexpr E error_or(G&& e) &&;
Mandates:
is_move_constructible_v<E> is
true and
is_convertible_v<G, E> is
true. Returns:
std::forward<G>(e) if
has_value() is
true,
std::move(error()) otherwise
. template<class F> constexpr auto and_then(F&& f) &;
template<class F> constexpr auto and_then(F&& f) const &;
Let
U be
remove_cvref_t<invoke_result_t<F>>.Constraints:
is_constructible_v<E, decltype(error())>> is
true. Mandates:
U is a specialization of
expected and
is_same_v<U::error_type, E> is
true. Effects: Equivalent to:
if (has_value())
return invoke(std::forward<F>(f));
else
return U(unexpect, error());
template<class F> constexpr auto and_then(F&& f) &&;
template<class F> constexpr auto and_then(F&& f) const &&;
Let
U be
remove_cvref_t<invoke_result_t<F>>.Constraints:
is_constructible_v<E, decltype(std::move(error()))> is
true. Mandates:
U is a specialization of
expected and
is_same_v<U::error_type, E> is
true. Effects: Equivalent to:
if (has_value())
return invoke(std::forward<F>(f));
else
return U(unexpect, std::move(error()));
template<class F> constexpr auto or_else(F&& f) &;
template<class F> constexpr auto or_else(F&& f) const &;
Let
G be
remove_cvref_t<invoke_result_t<F, decltype(error())>>.Mandates:
G is a specialization of
expected and
is_same_v<G::value_type, T> is
true. Effects: Equivalent to:
if (has_value())
return G();
else
return invoke(std::forward<F>(f), error());
template<class F> constexpr auto or_else(F&& f) &&;
template<class F> constexpr auto or_else(F&& f) const &&;
Let
G be
remove_cvref_t<invoke_result_t<F, decltype(std::move(error()))>>.Mandates:
G is a specialization of
expected and
is_same_v<G::value_type, T> is
true. Effects: Equivalent to:
if (has_value())
return G();
else
return invoke(std::forward<F>(f), std::move(error()));
Let
U be
remove_cv_t<invoke_result_t<F>>.Constraints:
is_constructible_v<E, decltype(error())> is
true. Mandates:
U is a valid value type for
expected. If
is_void_v<U> is
false, the declaration
U u(invoke(std::forward<F>(f)));
is well-formed
.Effects:
If
has_value() is
false, returns
expected<U, E>(unexpect, error()).Otherwise, if
is_void_v<U> is
false, returns an
expected<U, E> object whose
has_val member is
true and
val member is direct-non-list-initialized with
invoke(std::forward<F>(f)).Otherwise, evaluates
invoke(std::forward<F>(f)) and then returns
expected<U, E>().
Let
U be
remove_cv_t<invoke_result_t<F>>.Constraints:
is_constructible_v<E, decltype(std::move(error()))> is
true. Mandates:
U is a valid value type for
expected. If
is_void_v<U> is
false, the declaration
U u(invoke(std::forward<F>(f)));
is well-formed
.Effects:
If
has_value() is
false, returns
expected<U, E>(unexpect, std::move(error())).Otherwise, if
is_void_v<U> is
false, returns an
expected<U, E> object whose
has_val member is
true and
val member is direct-non-list-initialized with
invoke(std::forward<F>(f)).Otherwise, evaluates
invoke(std::forward<F>(f)) and then returns
expected<U, E>().
Let
G be
remove_cv_t<invoke_result_t<F, decltype(error())>>.Mandates:
G is a valid template argument
for
unexpected (
[expected.un.general]) and the declaration
G g(invoke(std::forward<F>(f), error()));
is well-formed
. Returns: If
has_value() is
true,
expected<T, G>(); otherwise, an
expected<T, G> object whose
has_val member is
false
and
unex member is direct-non-list-initialized with
invoke(std::forward<F>(f), error()). Let
G be
remove_cv_t<invoke_result_t<F, decltype(std::move(error()))>>.Mandates:
G is a valid template argument
for
unexpected (
[expected.un.general]) and the declaration
G g(invoke(std::forward<F>(f), std::move(error())));
is well-formed
. Returns: If
has_value() is
true,
expected<T, G>(); otherwise, an
expected<T, G> object whose
has_val member is
false
and
unex member is direct-non-list-initialized with
invoke(std::forward<F>(f), std::move(error())). template<class T2, class E2> requires is_void_v<T2>
friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
Constraints: The expression
x.error() == y.error() is well-formed and
its result is convertible to
bool. Returns: If
x.has_value() does not equal
y.has_value(),
false;
otherwise
x.has_value() || static_cast<bool>(x.error() == y.error()). template<class E2>
friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
Constraints: The expression
x.error() == e.error() is well-formed and
its result is convertible to
bool. Returns:
!x.has_value() && static_cast<bool>(x.error() == e.error()). The header defines a class template
and several related functions for representing
and manipulating fixed-size sequences of bits
.#include <string>
#include <iosfwd>
namespace std {
template<size_t N> class bitset;
template<size_t N>
constexpr bitset<N> operator&(const bitset<N>&, const bitset<N>&) noexcept;
template<size_t N>
constexpr bitset<N> operator|(const bitset<N>&, const bitset<N>&) noexcept;
template<size_t N>
constexpr bitset<N> operator^(const bitset<N>&, const bitset<N>&) noexcept;
template<class charT, class traits, size_t N>
basic_istream<charT, traits>&
operator>>(basic_istream<charT, traits>& is, bitset<N>& x);
template<class charT, class traits, size_t N>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x);
}
namespace std {
template<size_t N> class bitset {
public:
class reference {
public:
constexpr reference(const reference&) = default;
constexpr ~reference();
constexpr reference& operator=(bool x) noexcept;
constexpr reference& operator=(const reference&) noexcept;
constexpr bool operator~() const noexcept;
constexpr operator bool() const noexcept;
constexpr reference& flip() noexcept;
};
constexpr bitset() noexcept;
constexpr bitset(unsigned long long val) noexcept;
template<class charT, class traits, class Allocator>
constexpr explicit bitset(
const basic_string<charT, traits, Allocator>& str,
typename basic_string<charT, traits, Allocator>::size_type pos = 0,
typename basic_string<charT, traits, Allocator>::size_type n
= basic_string<charT, traits, Allocator>::npos,
charT zero = charT('0'),
charT one = charT('1'));
template<class charT, class traits>
constexpr explicit bitset(
basic_string_view<charT, traits> str,
typename basic_string_view<charT, traits>::size_type pos = 0,
typename basic_string_view<charT, traits>::size_type n
= basic_string_view<charT, traits>::npos,
charT zero = charT('0'),
charT one = charT('1'));
template<class charT>
constexpr explicit bitset(
const charT* str,
typename basic_string_view<charT>::size_type n = basic_string_view<charT>::npos,
charT zero = charT('0'),
charT one = charT('1'));
constexpr bitset& operator&=(const bitset& rhs) noexcept;
constexpr bitset& operator|=(const bitset& rhs) noexcept;
constexpr bitset& operator^=(const bitset& rhs) noexcept;
constexpr bitset& operator<<=(size_t pos) noexcept;
constexpr bitset& operator>>=(size_t pos) noexcept;
constexpr bitset operator<<(size_t pos) const noexcept;
constexpr bitset operator>>(size_t pos) const noexcept;
constexpr bitset& set() noexcept;
constexpr bitset& set(size_t pos, bool val = true);
constexpr bitset& reset() noexcept;
constexpr bitset& reset(size_t pos);
constexpr bitset operator~() const noexcept;
constexpr bitset& flip() noexcept;
constexpr bitset& flip(size_t pos);
constexpr bool operator[](size_t pos) const;
constexpr reference operator[](size_t pos);
constexpr unsigned long to_ulong() const;
constexpr unsigned long long to_ullong() const;
template<class charT = char,
class traits = char_traits<charT>,
class Allocator = allocator<charT>>
constexpr basic_string<charT, traits, Allocator>
to_string(charT zero = charT('0'), charT one = charT('1')) const;
constexpr size_t count() const noexcept;
constexpr size_t size() const noexcept;
constexpr bool operator==(const bitset& rhs) const noexcept;
constexpr bool test(size_t pos) const;
constexpr bool all() const noexcept;
constexpr bool any() const noexcept;
constexpr bool none() const noexcept;
};
template<class T> struct hash;
template<size_t N> struct hash<bitset<N>>;
}
The class template
bitset<N>
describes an object that can store a sequence consisting of a fixed number of
bits,
N.Each bit represents either the value zero (reset) or one (set)
. To
toggle
a bit is to change the value zero to one, or the value one to
zero
. Each bit has a non-negative position
pos. When converting
between an object of class
bitset<N>
and a value of some
integral type, bit position
pos corresponds to the
bit value
1 << pos. The integral value corresponding to two
or more bits is the sum of their bit values
.The functions described in
[template.bitset] can report three kinds of
errors, each associated with a distinct exception:
constexpr bitset() noexcept;
Effects: Initializes all bits in
*this to zero
. constexpr bitset(unsigned long long val) noexcept;
Effects: Initializes the first
M bit positions to the corresponding bit
values in
val. M is the smaller of
N and the number of bits in the value
representation (
[basic.types.general]) of
unsigned long long. If
M < N, the remaining bit positions are initialized to zero
.template<class charT, class traits, class Allocator>
constexpr explicit bitset(
const basic_string<charT, traits, Allocator>& str,
typename basic_string<charT, traits, Allocator>::size_type pos = 0,
typename basic_string<charT, traits, Allocator>::size_type n
= basic_string<charT, traits, Allocator>::npos,
charT zero = charT('0'),
charT one = charT('1'));
template<class charT, class traits>
constexpr explicit bitset(
basic_string_view<charT, traits> str,
typename basic_string_view<charT, traits>::size_type pos = 0,
typename basic_string_view<charT, traits>::size_type n
= basic_string_view<charT, traits>::npos,
charT zero = charT('0'),
charT one = charT('1'));
Effects: Determines the effective length
rlen of the initializing string as the smaller of
n and
str.size() - pos. Initializes the first
M bit
positions to values determined from the corresponding characters in the string
str. M is the smaller of
N and
rlen. An element of the constructed object has value zero if the
corresponding character in
str, beginning at position
pos, is
zero. Otherwise, the element has the value one
. Character position
pos + M - 1 corresponds to bit position zero
. Subsequent decreasing character positions correspond to increasing bit positions
.If
M < N, remaining bit positions are initialized to zero
.The function uses
traits::eq
to compare the character values
.Throws:
out_of_range if
pos > str.size() or
invalid_argument if any of
the
rlen characters in
str
beginning at position
pos
is other than
zero or
one. template<class charT>
constexpr explicit bitset(
const charT* str,
typename basic_string_view<charT>::size_type n = basic_string_view<charT>::npos,
charT zero = charT('0'),
charT one = charT('1'));
Effects: As if by:
bitset(n == basic_string_view<charT>::npos
? basic_string_view<charT>(str)
: basic_string_view<charT>(str, n),
0, n, zero, one)
constexpr bitset& operator&=(const bitset& rhs) noexcept;
Effects: Clears each bit in
*this
for which the corresponding bit in
rhs is clear, and leaves all other bits unchanged
. constexpr bitset& operator|=(const bitset& rhs) noexcept;
Effects: Sets each bit in
*this
for which the corresponding bit in
rhs is set, and leaves all other bits unchanged
. constexpr bitset& operator^=(const bitset& rhs) noexcept;
Effects: Toggles each bit in
*this
for which the corresponding bit in
rhs is set, and leaves all other bits unchanged
. constexpr bitset& operator<<=(size_t pos) noexcept;
Effects: Replaces each bit at position
I in
*this
with a value determined as follows:
- If I < pos, the new value is zero;
- If I >= pos, the new value is the previous
value of the bit at position I - pos.
constexpr bitset& operator>>=(size_t pos) noexcept;
Effects: Replaces each bit at position
I in
*this
with a value determined as follows:
- If pos >= N - I, the new value is zero;
- If pos < N - I, the new value is the previous value of the bit at position I + pos.
constexpr bitset operator<<(size_t pos) const noexcept;
Returns:
bitset(*this) <<= pos. constexpr bitset operator>>(size_t pos) const noexcept;
Returns:
bitset(*this) >>= pos. constexpr bitset& set() noexcept;
Effects: Sets all bits in
*this. constexpr bitset& set(size_t pos, bool val = true);
Effects: Stores a new value in the bit at position
pos in
*this. If
val is
true, the stored value is one, otherwise it is zero
.Throws:
out_of_range if
pos does not correspond to a valid bit position
. constexpr bitset& reset() noexcept;
Effects: Resets all bits in
*this. constexpr bitset& reset(size_t pos);
Effects: Resets the bit at position
pos in
*this. Throws:
out_of_range if
pos does not correspond to a valid bit position
. constexpr bitset operator~() const noexcept;
Effects: Constructs an object
x of class
bitset
and initializes it with
*this. constexpr bitset& flip() noexcept;
Effects: Toggles all bits in
*this. constexpr bitset& flip(size_t pos);
Effects: Toggles the bit at position
pos in
*this. Throws:
out_of_range if
pos does not correspond to a valid bit position
. constexpr bool operator[](size_t pos) const;
Hardened preconditions:
pos < size() is
true. Returns:
true if the bit at position
pos in
*this has the value
one, otherwise
false. constexpr bitset::reference operator[](size_t pos);
Hardened preconditions:
pos < size() is
true. Returns: An object of type
bitset::reference
such that
(*this)[pos] == this->test(pos),
and such that
(*this)[pos] = val
is equivalent to
this->set(pos, val). Remarks: For the purpose of determining the presence of a data
race (
[intro.multithread]), any access or update through the resulting
reference potentially accesses or modifies, respectively, the entire
underlying bitset
. constexpr unsigned long to_ulong() const;
Throws:
overflow_error if the integral value
x
corresponding to the bits in
*this
cannot be represented as type
unsigned long. constexpr unsigned long long to_ullong() const;
Throws:
overflow_error if the integral value
x
corresponding to the bits in
*this
cannot be represented as type
unsigned long long. template<class charT = char,
class traits = char_traits<charT>,
class Allocator = allocator<charT>>
constexpr basic_string<charT, traits, Allocator>
to_string(charT zero = charT('0'), charT one = charT('1')) const;
Effects: Constructs a string object of the appropriate type
and initializes it to a string of length
N characters
. Each character is determined by the value of its corresponding bit position in
*this. Character position
N - 1 corresponds to bit position zero
. Subsequent decreasing character positions correspond to increasing bit
positions
. Bit value zero becomes the character
zero,
bit value one becomes the character
one.Returns: The created object
. constexpr size_t count() const noexcept;
Returns: A count of the number of bits set in
*this. constexpr size_t size() const noexcept;
constexpr bool operator==(const bitset& rhs) const noexcept;
Returns:
true if the value of each bit in
*this
equals the value of the corresponding bit in
rhs. constexpr bool test(size_t pos) const;
Returns:
true
if the bit at position
pos
in
*this
has the value one
. Throws:
out_of_range if
pos does not correspond to a valid bit position
. constexpr bool all() const noexcept;
Returns:
count() == size(). constexpr bool any() const noexcept;
constexpr bool none() const noexcept;
template<size_t N> struct hash<bitset<N>>;
template<size_t N>
constexpr bitset<N> operator&(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns:
bitset<N>(lhs) &= rhs. template<size_t N>
constexpr bitset<N> operator|(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns:
bitset<N>(lhs) |= rhs. template<size_t N>
constexpr bitset<N> operator^(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
Returns:
bitset<N>(lhs) ^= rhs. template<class charT, class traits, size_t N>
basic_istream<charT, traits>&
operator>>(basic_istream<charT, traits>& is, bitset<N>& x);
Effects: Extracts up to
N characters from
is. Stores these characters in a temporary object
str of type
basic_string<charT, traits>,
then evaluates the expression
x = bitset<N>(str). Characters are extracted and stored until any of the following occurs:
- N characters have been extracted and stored;
- end-of-file occurs on the input sequence;
- the next input character is neither
is.widen('0')
nor
is.widen('1')
(in which case the input character is not extracted).
If
N > 0 and no characters are stored in
str,
ios_base::failbit is set in the input function's local error state
before
setstate is called
.template<class charT, class traits, size_t N>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x);
Returns:
os << x.template to_string<charT, traits, allocator<charT>>(
use_facet<ctype<charT>>(os.getloc()).widen('0'),
use_facet<ctype<charT>>(os.getloc()).widen('1'))
(see
[ostream.formatted])
. In the places where one would expect to pass a
pointer to a function to an algorithmic template (
[algorithms]), the
interface is specified to accept a function object
. This not only makes
algorithmic templates work with pointers to functions, but also enables them to
work with arbitrary function objects
.
[
Example 1:
If a C++ program wants to have a by-element addition of two vectors a
and b containing double and put the result into a,
it can do:
transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());
—
end example]
[
Example 2:
To negate every element of a:
transform(a.begin(), a.end(), a.begin(), negate<double>());
— end example]
The following definitions apply to this Clause:
A
call signature is the name of a return type followed by a
parenthesized comma-separated list of zero or more argument types
.A
call wrapper type is a type that holds a callable object
and supports a call operation that forwards to that object
.A call wrapper type may additionally hold
a sequence of objects and references
that may be passed as arguments to the target object
. The target object and bound argument entities of the call wrapper are
collectively referred to as
state entities.Define
INVOKE(f, t1, t2, …, tN) as follows:
- (t1.*f)(t2, …, tN) when f is a pointer to a
member function of a class T
and
is_same_v<T, remove_cvref_t<decltype(t1)>> ||
is_base_of_v<T, remove_cvref_t<decltype(t1)>> is true;
- (t1.get().*f)(t2, …, tN) when f is a pointer to a
member function of a class T
and remove_cvref_t<decltype(t1)> is a specialization of reference_wrapper;
- ((*t1).*f)(t2, …, tN) when f is a pointer to a
member function of a class T
and t1 does not satisfy the previous two items;
- t1.*f when N=1 and f is a pointer to
data member of a class T
and
is_same_v<T, remove_cvref_t<decltype(t1)>> ||
is_base_of_v<T, remove_cvref_t<decltype(t1)>> is true;
- t1.get().*f when N=1 and f is a pointer to
data member of a class T
and remove_cvref_t<decltype(t1)> is a specialization of reference_wrapper;
- (*t1).*f when N=1 and f is a pointer to
data member of a class T
and t1 does not satisfy the previous two items;
- f(t1, t2, …, tN) in all other cases.
Define
INVOKE<R>(f, t1, t2, …, tN) as
static_cast<void>(INVOKE(f, t1, t2, …, tN))
if
R is
cv void, otherwise
INVOKE(f, t1, t2, …, tN) implicitly converted
to
R. If
reference_converts_from_temporary_v<R, decltype(INVOKE(f, t1, t2, …, tN))>
is
true,
INVOKE<R>(f, t1, t2, …, tN)
is ill-formed
. An
argument forwarding call wrapper is a
call wrapper that can be called with an arbitrary argument list
and delivers the arguments to the target object as references
. This forwarding step delivers rvalue arguments as rvalue references
and lvalue arguments as lvalue references
. [
Note 1:
In a typical implementation, argument forwarding call wrappers have
an overloaded function call operator of the form
template<class... UnBoundArgs>
constexpr R operator()(UnBoundArgs&&... unbound_args) cv-qual;
—
end note]
This forwarding step delivers a state entity of type
T
as
cv T&
when the call is performed on an lvalue of the call wrapper type and
as
cv T&& otherwise,
where
cv represents the cv-qualifiers of the call wrapper and
where
cv shall be neither
volatile nor
const volatile. A
call pattern defines the semantics of invoking
a perfect forwarding call wrapper
. A postfix call performed on a perfect forwarding call wrapper is
expression-equivalent (
[defns.expression.equivalent]) to
an expression
e determined from its call pattern
cp
by replacing all occurrences
of the arguments of the call wrapper and its state entities
with references as described in the corresponding forwarding steps
.The copy/move constructor of an argument forwarding call wrapper has
the same apparent semantics
as if memberwise copy/move of its state entities
were performed (
[class.copy.ctor])
. [
Note 2:
This implies that each of the copy/move constructors has
the same exception-specification as
the corresponding implicit definition and is declared as
constexpr
if the corresponding implicit definition would be considered to be constexpr
. —
end note]
Argument forwarding call wrappers returned by
a given standard library function template have the same type
if the types of their corresponding state entities are the same
.template<class F, class... Args>
constexpr invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
noexcept(is_nothrow_invocable_v<F, Args...>);
Constraints:
is_invocable_v<F, Args...> is
true. Returns:
INVOKE(std::forward<F>(f), std::forward<Args>(args)...) (
[func.require])
. template<class R, class F, class... Args>
constexpr R invoke_r(F&& f, Args&&... args)
noexcept(is_nothrow_invocable_r_v<R, F, Args...>);
Constraints:
is_invocable_r_v<R, F, Args...> is
true. Returns:
INVOKE<R>(std::forward<F>(f), std::forward<Args>(args)...) (
[func.require])
. namespace std {
template<class T> class reference_wrapper {
public:
using type = T;
template<class U>
constexpr reference_wrapper(U&&) noexcept(see below);
constexpr reference_wrapper(const reference_wrapper& x) noexcept;
constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept;
constexpr operator T& () const noexcept;
constexpr T& get() const noexcept;
template<class... ArgTypes>
constexpr invoke_result_t<T&, ArgTypes...> operator()(ArgTypes&&...) const
noexcept(is_nothrow_invocable_v<T&, ArgTypes...>);
friend constexpr bool operator==(reference_wrapper, reference_wrapper);
friend constexpr bool operator==(reference_wrapper, const T&);
friend constexpr bool operator==(reference_wrapper, reference_wrapper<const T>);
friend constexpr auto operator<=>(reference_wrapper, reference_wrapper);
friend constexpr auto operator<=>(reference_wrapper, const T&);
friend constexpr auto operator<=>(reference_wrapper, reference_wrapper<const T>);
};
template<class T>
reference_wrapper(T&) -> reference_wrapper<T>;
}
The template parameter
T of
reference_wrapper
may be an incomplete type
. template<class U>
constexpr reference_wrapper(U&& u) noexcept(see below);
Let FUN denote the exposition-only functions
void FUN(T&) noexcept;
void FUN(T&&) = delete;
Constraints: The expression
FUN(declval<U>()) is well-formed and
is_same_v<remove_cvref_t<U>, reference_wrapper> is
false. Effects: Creates a variable
r
as if by
T& r = std::forward<U>(u),
then constructs a
reference_wrapper object
that stores a reference to
r. Remarks: The exception specification is equivalent to
noexcept(FUN(declval<U>())). constexpr reference_wrapper(const reference_wrapper& x) noexcept;
Effects: Constructs a
reference_wrapper object that
stores a reference to
x.get(). constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept;
Postconditions:
*this stores a reference to
x.get(). constexpr operator T& () const noexcept;
Returns: The stored reference
. constexpr T& get() const noexcept;
Returns: The stored reference
. template<class... ArgTypes>
constexpr invoke_result_t<T&, ArgTypes...>
operator()(ArgTypes&&... args) const noexcept(is_nothrow_invocable_v<T&, ArgTypes...>);
Mandates:
T is a complete type
. Returns:
INVOKE(get(), std::forward<ArgTypes>(args)...) (
[func.require])
. friend constexpr bool operator==(reference_wrapper x, reference_wrapper y);
Constraints: The expression
x.get() == y.get() is well-formed and
its result is convertible to
bool. Returns:
x.get() == y.get(). friend constexpr bool operator==(reference_wrapper x, const T& y);
Constraints: The expression
x.get() == y is well-formed and
its result is convertible to
bool. friend constexpr bool operator==(reference_wrapper x, reference_wrapper<const T> y);
Constraints:
is_const_v<T> is
false and
the expression
x.get() == y.get() is well-formed and
its result is convertible to
bool. Returns:
x.get() == y.get(). friend constexpr auto operator<=>(reference_wrapper x, reference_wrapper y);
Constraints: The expression
synth-three-way(x.get(), y.get())
is well-formed
. Returns:
synth-three-way(x.get(), y.get()). friend constexpr auto operator<=>(reference_wrapper x, const T& y);
Constraints: The expression
synth-three-way(x.get(), y)
is well-formed
. Returns:
synth-three-way(x.get(), y). friend constexpr auto operator<=>(reference_wrapper x, reference_wrapper<const T> y);
Constraints:
is_const_v<T> is
false. The expression
synth-three-way(x.get(), y.get())
is well-formed
.Returns:
synth-three-way(x.get(), y.get()). The template parameter
T of
the following
ref and
cref function templates
may be an incomplete type
.template<class T> constexpr reference_wrapper<T> ref(T& t) noexcept;
Returns:
reference_wrapper<T>(t). template<class T> constexpr reference_wrapper<T> ref(reference_wrapper<T> t) noexcept;
template<class T> constexpr reference_wrapper<const T> cref(const T& t) noexcept;
Returns:
reference_wrapper<const T>(t). template<class T> constexpr reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept;
namespace std {
template<class T>
constexpr bool is-ref-wrapper = false;
template<class T>
constexpr bool is-ref-wrapper<reference_wrapper<T>> = true;
template<class R, class T, class RQ, class TQ>
concept ref-wrap-common-reference-exists-with =
is-ref-wrapper<R> &&
requires { typename common_reference_t<typename R::type&, TQ>; } &&
convertible_to<RQ, common_reference_t<typename R::type&, TQ>>;
template<class R, class T, template<class> class RQual, template<class> class TQual>
requires (ref-wrap-common-reference-exists-with<R, T, RQual<R>, TQual<T>> &&
!ref-wrap-common-reference-exists-with<T, R, TQual<T>, RQual<R>>)
struct basic_common_reference<R, T, RQual, TQual> {
using type = common_reference_t<typename R::type&, TQual<T>>;
};
template<class T, class R, template<class> class TQual, template<class> class RQual>
requires (ref-wrap-common-reference-exists-with<R, T, RQual<R>, TQual<T>> &&
!ref-wrap-common-reference-exists-with<T, R, TQual<T>, RQual<R>>)
struct basic_common_reference<T, R, TQual, RQual> {
using type = common_reference_t<typename R::type&, TQual<T>>;
};
}
The library provides basic function object classes for all of the arithmetic
operators in the language (
[expr.mul],
[expr.add])
.template<class T = void> struct plus {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template<> struct plus<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) + std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) + std::forward<U>(u));
Returns:
std::forward<T>(t) + std::forward<U>(u). template<class T = void> struct minus {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template<> struct minus<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) - std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) - std::forward<U>(u));
Returns:
std::forward<T>(t) - std::forward<U>(u). template<class T = void> struct multiplies {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template<> struct multiplies<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) * std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) * std::forward<U>(u));
Returns:
std::forward<T>(t) * std::forward<U>(u). template<class T = void> struct divides {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template<> struct divides<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) / std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) / std::forward<U>(u));
Returns:
std::forward<T>(t) / std::forward<U>(u). template<class T = void> struct modulus {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template<> struct modulus<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) % std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) % std::forward<U>(u));
Returns:
std::forward<T>(t) % std::forward<U>(u). template<class T = void> struct negate {
constexpr T operator()(const T& x) const;
};
constexpr T operator()(const T& x) const;
template<> struct negate<void> {
template<class T> constexpr auto operator()(T&& t) const
-> decltype(-std::forward<T>(t));
using is_transparent = unspecified;
};
template<class T> constexpr auto operator()(T&& t) const
-> decltype(-std::forward<T>(t));
Returns:
-std::forward<T>(t). The library provides basic function object classes for all of the comparison
operators in the language (
[expr.rel],
[expr.eq])
.For templates
less,
greater,
less_equal, and
greater_equal, the specializations for any pointer type
yield a result consistent with the
implementation-defined strict total order over pointers (
[defns.order.ptr])
. [
Note 1:
If
a < b is well-defined
for pointers
a and
b of type
P,
then
(a < b) == less<P>()(a, b),
(a > b) == greater<P>()(a, b), and so forth
. —
end note]
For template specializations
less<void>,
greater<void>,
less_equal<void>, and
greater_equal<void>,
if the call operator calls a built-in operator comparing pointers,
the call operator yields a result consistent
with the implementation-defined strict total order over pointers
.template<class T = void> struct equal_to {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template<> struct equal_to<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) == std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) == std::forward<U>(u));
Returns:
std::forward<T>(t) == std::forward<U>(u). template<class T = void> struct not_equal_to {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template<> struct not_equal_to<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) != std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) != std::forward<U>(u));
Returns:
std::forward<T>(t) != std::forward<U>(u). template<class T = void> struct greater {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template<> struct greater<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) > std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) > std::forward<U>(u));
Returns:
std::forward<T>(t) > std::forward<U>(u). template<class T = void> struct less {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template<> struct less<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) < std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) < std::forward<U>(u));
Returns:
std::forward<T>(t) < std::forward<U>(u). template<class T = void> struct greater_equal {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template<> struct greater_equal<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) >= std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) >= std::forward<U>(u));
Returns:
std::forward<T>(t) >= std::forward<U>(u). template<class T = void> struct less_equal {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template<> struct less_equal<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) <= std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) <= std::forward<U>(u));
Returns:
std::forward<T>(t) <= std::forward<U>(u). namespace std {
struct compare_three_way {
template<class T, class U>
constexpr auto operator()(T&& t, U&& u) const;
using is_transparent = unspecified;
};
}
template<class T, class U>
constexpr auto operator()(T&& t, U&& u) const;
Preconditions: If the expression
std::forward<T>(t) <=> std::forward<U>(u) results in
a call to a built-in operator
<=> comparing pointers of type
P,
the conversion sequences from both
T and
U to
P
are equality-preserving (
[concepts.equality]);
otherwise,
T and
U model
three_way_comparable_with. Effects:
- If the expression std::forward<T>(t) <=> std::forward<U>(u) results in
a call to a built-in operator <=> comparing pointers of type P,
returns strong_ordering::less
if (the converted value of) t precedes u
in the implementation-defined strict total order
over pointers ([defns.order.ptr]),
strong_ordering::greater
if u precedes t, and
otherwise strong_ordering::equal.
- Otherwise, equivalent to: return std::forward<T>(t) <=> std::forward<U>(u);
struct ranges::equal_to {
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
using is_transparent = unspecified;
};
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
Preconditions: If the expression
std::forward<T>(t) == std::forward<U>(u)
results in a call to a built-in operator
== comparing pointers of type
P, the conversion sequences from both
T and
U to
P
are equality-preserving (
[concepts.equality]);
otherwise,
T and
U model
equality_comparable_with. Effects:
- If the expression std::forward<T>(t) == std::forward<U>(u) results in
a call to a built-in operator == comparing pointers:
returns false if either (the converted value of) t precedes
u or u precedes t in the implementation-defined strict
total order over pointers ([defns.order.ptr]) and otherwise true.
- Otherwise, equivalent to:
return std::forward<T>(t) == std::forward<U>(u);
struct ranges::not_equal_to {
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
using is_transparent = unspecified;
};
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
Effects: Equivalent to:
return !ranges::equal_to{}(std::forward<T>(t), std::forward<U>(u));
struct ranges::greater {
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
using is_transparent = unspecified;
};
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
Effects: Equivalent to:
return ranges::less{}(std::forward<U>(u), std::forward<T>(t));
struct ranges::less {
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
using is_transparent = unspecified;
};
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
Preconditions: If the expression
std::forward<T>(t) < std::forward<U>(u) results in a
call to a built-in operator
< comparing pointers of type
P, the
conversion sequences from both
T and
U to
P are
equality-preserving (
[concepts.equality]);
otherwise,
T and
U model
totally_ordered_with. For any expressions
ET and
EU such that
decltype((ET)) is
T and
decltype((EU)) is
U, exactly one of
ranges::less{}(ET, EU),
ranges::less{}(EU, ET), or
ranges::equal_to{}(ET, EU)
is
true.Effects:
- If the expression std::forward<T>(t) < std::forward<U>(u) results in a
call to a built-in operator < comparing pointers:
returns true if (the converted value of) t precedes u in
the implementation-defined strict total order over pointers ([defns.order.ptr])
and otherwise false.
- Otherwise, equivalent to:
return std::forward<T>(t) < std::forward<U>(u);
struct ranges::greater_equal {
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
using is_transparent = unspecified;
};
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
Effects: Equivalent to:
return !ranges::less{}(std::forward<T>(t), std::forward<U>(u));
struct ranges::less_equal {
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
using is_transparent = unspecified;
};
template<class T, class U>
constexpr bool operator()(T&& t, U&& u) const;
Effects: Equivalent to:
return !ranges::less{}(std::forward<U>(u), std::forward<T>(t));
template<class T = void> struct logical_and {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template<> struct logical_and<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) && std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) && std::forward<U>(u));
Returns:
std::forward<T>(t) && std::forward<U>(u). template<class T = void> struct logical_or {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template<> struct logical_or<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) || std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) || std::forward<U>(u));
Returns:
std::forward<T>(t) || std::forward<U>(u). template<class T = void> struct logical_not {
constexpr bool operator()(const T& x) const;
};
constexpr bool operator()(const T& x) const;
template<> struct logical_not<void> {
template<class T> constexpr auto operator()(T&& t) const
-> decltype(!std::forward<T>(t));
using is_transparent = unspecified;
};
template<class T> constexpr auto operator()(T&& t) const
-> decltype(!std::forward<T>(t));
Returns:
!std::forward<T>(t). template<class T = void> struct bit_and {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template<> struct bit_and<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) & std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) & std::forward<U>(u));
Returns:
std::forward<T>(t) & std::forward<U>(u). template<class T = void> struct bit_or {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template<> struct bit_or<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) | std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) | std::forward<U>(u));
Returns:
std::forward<T>(t) | std::forward<U>(u). template<class T = void> struct bit_xor {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template<> struct bit_xor<void> {
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) ^ std::forward<U>(u));
using is_transparent = unspecified;
};
template<class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) ^ std::forward<U>(u));
Returns:
std::forward<T>(t) ^ std::forward<U>(u). template<class T = void> struct bit_not {
constexpr T operator()(const T& x) const;
};
constexpr T operator()(const T& x) const;
template<> struct bit_not<void> {
template<class T> constexpr auto operator()(T&& t) const
-> decltype(~std::forward<T>(t));
using is_transparent = unspecified;
};
template<class T> constexpr auto operator()(T&& t) const
-> decltype(~std::forward<T>(t));
Returns:
~std::forward<T>(t). struct identity {
template<class T>
constexpr T&& operator()(T&& t) const noexcept;
using is_transparent = unspecified;
};
template<class T>
constexpr T&& operator()(T&& t) const noexcept;
Effects: Equivalent to: return std::forward<T>(t);
template<class F> constexpr unspecified not_fn(F&& f);
In the text that follows:
- g is a value of the result of a not_fn invocation,
- FD is the type decay_t<F>,
- fd is the target object of g ([func.def])
of type FD,
direct-non-list-initialized with std::forward<F>(f),
- call_args is an argument pack
used in a function call expression ([expr.call]) of g.
Mandates:
is_constructible_v<FD, F> && is_move_constructible_v<FD>
is
true. Returns: A perfect forwarding call wrapper (
[func.require])
g
with call pattern
!invoke(fd, call_args...). Throws: Any exception thrown by the initialization of
fd. template<auto f> constexpr unspecified not_fn() noexcept;
In the text that follows:
- F is the type of f,
- g is a value of the result of a not_fn invocation,
- call_args is an argument pack
used in a function call expression ([expr.call]) of g.
Mandates: If
is_pointer_v<F> || is_member_pointer_v<F> is
true,
then
f != nullptr is
true. Returns: A perfect forwarding call wrapper (
[func.require])
g that
does not have state entities, and
has the call pattern
!invoke(f, call_args...). template<class F, class... Args>
constexpr unspecified bind_front(F&& f, Args&&... args);
template<class F, class... Args>
constexpr unspecified bind_back(F&& f, Args&&... args);
Within this subclause:
- g is a value of
the result of a bind_front or bind_back invocation,
- FD is the type decay_t<F>,
- fd is the target object of g ([func.def])
of type FD,
direct-non-list-initialized with std::forward<F>(f),
- BoundArgs is a pack
that denotes decay_t<Args>...,
- bound_args is
a pack of bound argument entities of g ([func.def])
of types BoundArgs...,
direct-non-list-initialized with std::forward<Args>(args)...,
respectively, and
- call_args is an argument pack used in
a function call expression ([expr.call]) of g.
Mandates:
is_constructible_v<FD, F> &&
is_move_constructible_v<FD> &&
(is_constructible_v<BoundArgs, Args> && ...) &&
(is_move_constructible_v<BoundArgs> && ...)
is
true. Returns: A perfect forwarding call wrapper (
[func.require])
g
with call pattern:
- invoke(fd, bound_args..., call_args...)
for a bind_front invocation, or
- invoke(fd, call_args..., bound_args...)
for a bind_back invocation.
Throws: Any exception thrown by
the initialization of the state entities of
g (
[func.def])
. template<auto f, class... Args>
constexpr unspecified bind_front(Args&&... args);
template<auto f, class... Args>
constexpr unspecified bind_back(Args&&... args);
Within this subclause:
- F is the type of f,
- g is a value of the result of
a bind_front or bind_back invocation,
- BoundArgs is a pack that denotes decay_t<Args>...,
- bound_args is a pack of bound argument entities of
g ([func.def]) of types BoundArgs...,
direct-non-list-initialized with std::forward<Args>(args)...,
respectively, and
- call_args is an argument pack used in
a function call expression ([expr.call]) of g.
Mandates:
- (is_constructible_v<BoundArgs, Args> && ...) is true, and
- (is_move_constructible_v<BoundArgs> && ...) is true, and
- if is_pointer_v<F> || is_member_pointer_v<F> is true,
then f != nullptr is true.
Returns: A perfect forwarding call wrapper (
[func.require])
g that
does not have a target object, and has the call pattern:
- invoke(f, bound_args..., call_args...)
for a bind_front invocation, or
- invoke(f, call_args..., bound_args...)
for a bind_back invocation.
Throws: Any exception thrown by the initialization of
bound_args. Subclause
[func.bind] describes a uniform mechanism for binding
arguments of callable objects
.namespace std {
template<class T> struct is_bind_expression;
}
The class template
is_bind_expression can be used to detect function objects
generated by
bind. The function template
bind
uses
is_bind_expression to detect subexpressions
. The implementation
provides a definition that has a base characteristic of
true_type if
T is a type returned from
bind,
otherwise it has a base characteristic of
false_type. A program may specialize this template for a program-defined type
T
to have a base characteristic of
true_type to indicate that
T should be treated as a subexpression in a
bind call
. namespace std {
template<class T> struct is_placeholder;
}
The class template
is_placeholder can be used to detect the standard placeholders
_1,
_2, and so on (
[func.bind.place])
. The function template
bind uses
is_placeholder to detect placeholders
. The implementation
provides a definition that has the base characteristic of
integral_constant<int, J> if
T is the type of
std::placeholders::_J, otherwise it has a
base characteristic of
integral_constant<int, 0>. A program
may specialize this template for a program-defined type
T to
have a base characteristic of
integral_constant<int, N>
with
N > 0 to indicate that
T should be
treated as a placeholder type
. In the text that follows:
- g is a value of the result of a bind invocation,
- FD is the type decay_t<F>,
- fd is an lvalue that
is a target object of g ([func.def]) of type FD
direct-non-list-initialized with std::forward<F>(f),
- Ti is the ith type in the template parameter pack BoundArgs,
- TDi is the type decay_t<Ti>,
- ti is the ith argument in the function parameter pack bound_args,
- tdi is a bound argument entity
of g ([func.def]) of type TDi
direct-non-list-initialized with
std::forward<Ti>(ti),
- Uj is the jth deduced type of the UnBoundArgs&&... parameter
of the argument forwarding call wrapper, and
- uj is the jth argument associated with Uj.
template<class F, class... BoundArgs>
constexpr unspecified bind(F&& f, BoundArgs&&... bound_args);
template<class R, class F, class... BoundArgs>
constexpr unspecified bind(F&& f, BoundArgs&&... bound_args);
Mandates:
is_constructible_v<FD, F> is
true. For each
Ti
in
BoundArgs,
is_constructible_v<TDi, Ti> is
true. INVOKE(fd, w1, w2, …,
wN) (
[func.require]) is a valid expression for some
values
w1,
w2,
…,
wN, where
N has the value
sizeof...(bound_args). A program that attempts to invoke a volatile-qualified
g
is ill-formed
. When
g is not volatile-qualified, invocation of
g(u1, u2, …, uM)
is expression-equivalent (
[defns.expression.equivalent]) to
INVOKE(static_cast<Vfd>(vfd),
static_cast<V1>(v1), static_cast<V2>(v2), …, static_cast<VN>(vN))
for the first overload, and
INVOKE<R>(static_cast<Vfd>(vfd),
static_cast<V1>(v1), static_cast<V2>(v2), …, static_cast<VN>(vN))
for the second overload,
where the values and types of the target argument
vfd and
of the bound arguments
v1,
v2,
…,
vN are determined as specified below
. Throws: Any exception thrown by the initialization of
the state entities of
g. The values of the
bound arguments v1,
v2,
…,
vN and their
corresponding types
V1,
V2,
…,
VN depend on the
types
TDi derived from
the call to
bind and the
cv-qualifiers
cv of the call wrapper
g as follows:
- if TDi is reference_wrapper<T>, the
argument is tdi.get() and its type Vi is T&;
- if the value of is_bind_expression_v<TDi>
is true, the argument is
static_cast<cv TDi&>(tdi)(std::forward<Uj>(uj)...)
and its type Vi is
invoke_result_t<cv TDi&, Uj...>&&;
- if the value j of is_placeholder_v<TDi>
is not zero, the argument is std::forward<Uj>(uj)
and its type Vi
is Uj&&;
- otherwise, the value is tdi and its type Vi
is cv TDi&.
The value of the target argument
vfd is
fd and
its corresponding type
Vfd is
cv FD&. namespace std::placeholders {
see below _1;
see below _2;
⋮
see below _M;
}
The number
M of placeholders is
implementation-defined
. It is
implementation-defined whether
placeholder types meet the
Cpp17CopyAssignable requirements,
but if so, their copy assignment operators are
constexpr functions that do not throw exceptions
. Placeholders should be defined as:
inline constexpr unspecified _1{};
If they are not, they are declared as:
extern unspecified _1;
template<class R, class T> constexpr unspecified mem_fn(R T::* pm) noexcept;
Returns: A simple call wrapper (
[func.require])
fn
with call pattern
invoke(pmd, call_args...), where
pmd is the target object of
fn of type
R T::*
direct-non-list-initialized with
pm, and
call_args is an argument pack
used in a function call expression (
[expr.call]) of
fn. Subclause
[func.wrap] describes polymorphic wrapper classes that
encapsulate arbitrary callable objects
.Let
t be an object of a type that is a specialization of
function,
copyable_function, or
move_only_function,
such that the target object
x of
t has a type that
is a specialization of
function,
copyable_function, or
move_only_function. Each argument of the
invocation of
x evaluated as part of the invocation of
t
may alias an argument in the same position in the invocation of
t that
has the same type, even if the corresponding parameter is not of reference type
. [
Example 1:
move_only_function<void(T)> f{copyable_function<void(T)>{[](T) {}}};
T t;
f(t);
—
end example]
Recommended practice: Implementations should avoid double wrapping when
constructing polymorphic wrappers from one another
. An exception of type
bad_function_call is thrown by
function::operator() (
[func.wrap.func.inv])
when the function wrapper object has no target
.namespace std {
class bad_function_call : public exception {
public:
const char* what() const noexcept override;
};
}
const char* what() const noexcept override;
Returns: An
implementation-defined
ntbs.
namespace std {
template<class R, class... ArgTypes>
class function<R(ArgTypes...)> {
public:
using result_type = R;
function() noexcept;
function(nullptr_t) noexcept;
function(const function&);
function(function&&) noexcept;
template<class F> function(F&&);
function& operator=(const function&);
function& operator=(function&&);
function& operator=(nullptr_t) noexcept;
template<class F> function& operator=(F&&);
template<class F> function& operator=(reference_wrapper<F>) noexcept;
~function();
void swap(function&) noexcept;
explicit operator bool() const noexcept;
R operator()(ArgTypes...) const;
const type_info& target_type() const noexcept;
template<class T> T* target() noexcept;
template<class T> const T* target() const noexcept;
};
template<class R, class... ArgTypes>
function(R(*)(ArgTypes...)) -> function<R(ArgTypes...)>;
template<class F> function(F) -> function<see below>;
}
The
function class template provides polymorphic wrappers that
generalize the notion of a function pointer
. Wrappers can store, copy,
and call arbitrary callable objects (
[func.def]), given a call
signature (
[func.def])
.The
function class template is a call
wrapper (
[func.def]) whose call signature (
[func.def])
is
R(ArgTypes...).[
Note 1:
The types deduced by the deduction guides for
function
might change in future revisions of C++
. —
end note]
function(nullptr_t) noexcept;
function(const function& f);
Postconditions:
!*this if
!f; otherwise,
the target object of
*this is a copy of the target object of
f. Throws: Nothing if
f's target is
a specialization of
reference_wrapper or
a function pointer
. Otherwise, may throw
bad_alloc
or any exception thrown by the copy constructor of the stored callable object
.Recommended practice: Implementations should avoid the use of
dynamically allocated memory for small callable objects, for example, where
f's target is an object holding only a pointer or reference
to an object and a member function pointer
. function(function&& f) noexcept;
Postconditions: If
!f,
*this has no target;
otherwise, the target of
*this is equivalent to
the target of
f before the construction, and
f is in a valid state with an unspecified value
. Recommended practice: Implementations should avoid the use of
dynamically allocated memory for small callable objects, for example,
where
f's target is an object holding only a pointer or reference
to an object and a member function pointer
. template<class F> function(F&& f);
Constraints:
- is_same_v<remove_cvref_t<F>, function> is false, and
- is_invocable_r_v<R, FD&, ArgTypes...> is true.
Mandates:
- is_copy_constructible_v<FD> is true, and
- is_constructible_v<FD, F> is true.
Postconditions:
!*this is
true if any of the following hold:
f is a null function pointer value
. f is a null member pointer value
. remove_cvref_t<F> is
a specialization of the
function class template, and
!f is
true.
Otherwise,
*this has a target object of type
FD
direct-non-list-initialized with
std::forward<F>(f).Throws: Nothing if
FD is
a specialization of
reference_wrapper or
a function pointer type
. Otherwise, may throw
bad_alloc or
any exception thrown by the initialization of the target object
.Recommended practice: Implementations should avoid the use of
dynamically allocated memory for small callable objects, for example,
where
f refers to an object holding only a pointer or
reference to an object and a member function pointer
. template<class F> function(F) -> function<see below>;
Constraints:
&F::operator() is well-formed when treated as an unevaluated operand and either
- F::operator() is a non-static member function and
decltype(&F::operator()) is either of the form
R(G::*)(A...) cv &opt noexceptopt
or of the form
R(*)(G, A...) noexceptopt
for a type G, or
- F::operator() is a static member function and
decltype(&F::operator()) is of the form
R(*)(A...) noexceptopt.
Remarks: The deduced type is
function<R(A...)>. [
Example 1:
void f() {
int i{5};
function g = [&](double) { return i; };
}
—
end example]
function& operator=(const function& f);
Effects: As if by function(f).swap(*this);
function& operator=(function&& f);
Effects: Replaces the target of
*this
with the target of
f. function& operator=(nullptr_t) noexcept;
Effects: If
*this != nullptr, destroys the target of
this. Postconditions:
!(*this). template<class F> function& operator=(F&& f);
Constraints:
is_invocable_r_v<R, decay_t<F>&, ArgTypes...> is
true. Effects: As if by: function(std::forward<F>(f)).swap(*this);
template<class F> function& operator=(reference_wrapper<F> f) noexcept;
Effects: As if by: function(f).swap(*this);
Effects: If
*this != nullptr, destroys the target of
this. void swap(function& other) noexcept;
Effects: Interchanges the target objects of
*this and
other. explicit operator bool() const noexcept;
Returns:
true if
*this has a target, otherwise
false. R operator()(ArgTypes... args) const;
Returns:
INVOKE<R>(f, std::forward<ArgTypes>(args)...) (
[func.require]),
where
f is the target object (
[func.def]) of
*this. Throws:
bad_function_call if
!*this; otherwise, any
exception thrown by the target object
. const type_info& target_type() const noexcept;
Returns: If
*this has a target of type
T,
typeid(T); otherwise,
typeid(void). template<class T> T* target() noexcept;
template<class T> const T* target() const noexcept;
Returns: If
target_type() == typeid(T)
a pointer to the stored function target; otherwise a null pointer
. template<class R, class... ArgTypes>
bool operator==(const function<R(ArgTypes...)>& f, nullptr_t) noexcept;
template<class R, class... ArgTypes>
void swap(function<R(ArgTypes...)>& f1, function<R(ArgTypes...)>& f2) noexcept;
Effects: As if by: f1.swap(f2);
The header provides partial specializations of
move_only_function
for each combination of the possible replacements
of the placeholders
cv,
ref, and
noex where
- cv is either const or empty,
- ref is either &, &&, or empty, and
- noex is either true or false.
For each of the possible combinations of the placeholders mentioned above,
there is a placeholder
inv-quals defined as follows:
- If ref is empty, let inv-quals be cv&,
- otherwise, let inv-quals be cv ref.
namespace std {
template<class R, class... ArgTypes>
class move_only_function<R(ArgTypes...) cv ref noexcept(noex)> {
public:
using result_type = R;
move_only_function() noexcept;
move_only_function(nullptr_t) noexcept;
move_only_function(move_only_function&&) noexcept;
template<class F> move_only_function(F&&);
template<class T, class... Args>
explicit move_only_function(in_place_type_t<T>, Args&&...);
template<class T, class U, class... Args>
explicit move_only_function(in_place_type_t<T>, initializer_list<U>, Args&&...);
move_only_function& operator=(move_only_function&&);
move_only_function& operator=(nullptr_t) noexcept;
template<class F> move_only_function& operator=(F&&);
~move_only_function();
explicit operator bool() const noexcept;
R operator()(ArgTypes...) cv ref noexcept(noex);
void swap(move_only_function&) noexcept;
friend void swap(move_only_function&, move_only_function&) noexcept;
friend bool operator==(const move_only_function&, nullptr_t) noexcept;
private:
template<class VT>
static constexpr bool is-callable-from = see below;
};
}
The
move_only_function class template provides polymorphic wrappers
that generalize the notion of a callable object (
[func.def])
. These wrappers can store, move, and call arbitrary callable objects,
given a call signature
.Recommended practice: Implementations should avoid the use of dynamically allocated memory
for a small contained value
. [
Note 1:
Such small-object optimization can only be applied to a type
T
for which
is_nothrow_move_constructible_v<T> is
true. —
end note]
template<class VT>
static constexpr bool is-callable-from = see below;
If noex is true,
is-callable-from<VT> is equal to:
is_nothrow_invocable_r_v<R, VT cv ref, ArgTypes...> &&
is_nothrow_invocable_r_v<R, VT inv-quals, ArgTypes...>
Otherwise, is-callable-from<VT> is equal to:
is_invocable_r_v<R, VT cv ref, ArgTypes...> &&
is_invocable_r_v<R, VT inv-quals, ArgTypes...>
move_only_function() noexcept;
move_only_function(nullptr_t) noexcept;
Postconditions:
*this has no target object
. move_only_function(move_only_function&& f) noexcept;
Postconditions: The target object of
*this is
the target object
f had before construction, and
f is in a valid state with an unspecified value
. template<class F> move_only_function(F&& f);
Constraints:
- remove_cvref_t<F> is not the same type as move_only_function, and
- remove_cvref_t<F> is not a specialization of in_place_type_t, and
- is-callable-from<VT> is true.
Mandates:
is_constructible_v<VT, F> is
true. Postconditions:
*this has no target object if any of the following hold:
- f is a null function pointer value, or
- f is a null member pointer value, or
- remove_cvref_t<F> is a specialization of
the move_only_function class template,
and f has no target object.
Otherwise,
*this has a target object of type
VT
direct-non-list-initialized with
std::forward<F>(f).Throws: Any exception thrown by the initialization of the target object
. May throw
bad_alloc unless
VT is
a function pointer or a specialization of
reference_wrapper.template<class T, class... Args>
explicit move_only_function(in_place_type_t<T>, Args&&... args);
Constraints:
- is_constructible_v<VT, Args...> is true, and
- is-callable-from<VT> is true.
Mandates:
VT is the same type as
T. Postconditions:
*this has a target object of type
VT
direct-non-list-initialized with
std::forward<Args>(args).... Throws: Any exception thrown by the initialization of the target object
. May throw
bad_alloc unless
VT is
a function pointer or a specialization of
reference_wrapper.template<class T, class U, class... Args>
explicit move_only_function(in_place_type_t<T>, initializer_list<U> ilist, Args&&... args);
Constraints:
- is_constructible_v<VT, initializer_list<U>&, Args...> is
true, and
- is-callable-from<VT> is true.
Mandates:
VT is the same type as
T. Postconditions:
*this has a target object of type
VT
direct-non-list-initialized with
ilist, std::forward<Args>(args).... Throws: Any exception thrown by the initialization of the target object
. May throw
bad_alloc unless
VT is
a function pointer or a specialization of
reference_wrapper.move_only_function& operator=(move_only_function&& f);
Effects: Equivalent to: move_only_function(std::move(f)).swap(*this);
move_only_function& operator=(nullptr_t) noexcept;
Effects: Destroys the target object of
*this, if any
. template<class F> move_only_function& operator=(F&& f);
Effects: Equivalent to: move_only_function(std::forward<F>(f)).swap(*this);
Effects: Destroys the target object of
*this, if any
. explicit operator bool() const noexcept;
Returns:
true if
*this has a target object, otherwise
false. R operator()(ArgTypes... args) cv ref noexcept(noex);
Preconditions:
*this has a target object
. Effects: Equivalent to:
return INVOKE<R>(static_cast<F inv-quals>(f), std::forward<ArgTypes>(args)...);
where
f is an lvalue designating the target object of
*this and
F is the type of
f. void swap(move_only_function& other) noexcept;
Effects: Exchanges the target objects of
*this and
other. friend void swap(move_only_function& f1, move_only_function& f2) noexcept;
Effects: Equivalent to
f1.swap(f2). friend bool operator==(const move_only_function& f, nullptr_t) noexcept;
Returns:
true if
f has no target object, otherwise
false. The header provides partial specializations of
copyable_function
for each combination of the possible replacements
of the placeholders
cv,
ref, and
noex where
- cv is either const or empty,
- ref is either &, &&, or empty, and
- noex is either true or false.
For each of the possible combinations of the placeholders mentioned above,
there is a placeholder
inv-quals defined as follows:
- If ref is empty, let inv-quals be cv&,
- otherwise, let inv-quals be cv ref.
namespace std {
template<class R, class... ArgTypes>
class copyable_function<R(ArgTypes...) cv ref noexcept(noex)> {
public:
using result_type = R;
copyable_function() noexcept;
copyable_function(nullptr_t) noexcept;
copyable_function(const copyable_function&);
copyable_function(copyable_function&&) noexcept;
template<class F> copyable_function(F&&);
template<class T, class... Args>
explicit copyable_function(in_place_type_t<T>, Args&&...);
template<class T, class U, class... Args>
explicit copyable_function(in_place_type_t<T>, initializer_list<U>, Args&&...);
copyable_function& operator=(const copyable_function&);
copyable_function& operator=(copyable_function&&);
copyable_function& operator=(nullptr_t) noexcept;
template<class F> copyable_function& operator=(F&&);
~copyable_function();
explicit operator bool() const noexcept;
R operator()(ArgTypes...) cv ref noexcept(noex);
void swap(copyable_function&) noexcept;
friend void swap(copyable_function&, copyable_function&) noexcept;
friend bool operator==(const copyable_function&, nullptr_t) noexcept;
private:
template<class VT>
static constexpr bool is-callable-from = see below;
};
}
The
copyable_function class template provides polymorphic wrappers
that generalize the notion of a callable object (
[func.def])
. These wrappers can store, copy, move, and call arbitrary callable objects,
given a call signature
.Recommended practice: Implementations should avoid the use of dynamically allocated memory
for a small contained value
. [
Note 1:
Such small-object optimization can only be applied to a type
T
for which
is_nothrow_move_constructible_v<T> is
true. —
end note]
template<class VT>
static constexpr bool is-callable-from = see below;
If noex is true,
is-callable-from<VT> is equal to:
is_nothrow_invocable_r_v<R, VT cv ref, ArgTypes...> &&
is_nothrow_invocable_r_v<R, VT inv-quals, ArgTypes...>
Otherwise, is-callable-from<VT> is equal to:
is_invocable_r_v<R, VT cv ref, ArgTypes...> &&
is_invocable_r_v<R, VT inv-quals, ArgTypes...>
copyable_function() noexcept;
copyable_function(nullptr_t) noexcept;
Postconditions:
*this has no target object
. copyable_function(const copyable_function& f);
Postconditions:
*this has no target object if
f had no target object
. Otherwise, the target object of
*this
is a copy of the target object of
f.Throws: Any exception thrown by the initialization of the target object
. copyable_function(copyable_function&& f) noexcept;
Postconditions: The target object of
*this is
the target object
f had before construction, and
f is in a valid state with an unspecified value
. template<class F> copyable_function(F&& f);
Constraints:
- remove_cvref_t<F> is not the same type as copyable_function, and
- remove_cvref_t<F> is not a specialization of in_place_type_t, and
- is-callable-from<VT> is true.
Mandates:
- is_constructible_v<VT, F> is true, and
- is_copy_constructible_v<VT> is true.
Postconditions:
*this has no target object if any of the following hold:
- f is a null function pointer value, or
- f is a null member pointer value, or
- remove_cvref_t<F> is a specialization of
the copyable_function class template,
and f has no target object.
Otherwise,
*this has a target object of type
VT
direct-non-list-initialized with
std::forward<F>(f).Throws: Any exception thrown by the initialization of the target object
. May throw
bad_alloc unless
VT is
a function pointer or a specialization of
reference_wrapper.template<class T, class... Args>
explicit copyable_function(in_place_type_t<T>, Args&&... args);
Constraints:
- is_constructible_v<VT, Args...> is true, and
- is-callable-from<VT> is true.
Mandates:
- VT is the same type as T, and
- is_copy_constructible_v<VT> is true.
Postconditions:
*this has a target object of type
VT
direct-non-list-initialized with
std::forward<Args>(args).... Throws: Any exception thrown by the initialization of the target object
. May throw
bad_alloc unless
VT is
a pointer or a specialization of
reference_wrapper.template<class T, class U, class... Args>
explicit copyable_function(in_place_type_t<T>, initializer_list<U> ilist, Args&&... args);
Constraints:
- is_constructible_v<VT, initializer_list<U>&, Args...> is
true, and
- is-callable-from<VT> is true.
Mandates:
- VT is the same type as T, and
- is_copy_constructible_v<VT> is true.
Postconditions:
*this has a target object of type
VT
direct-non-list-initialized with
ilist, std::forward<Args>(args).... Throws: Any exception thrown by the initialization of the target object
. May throw
bad_alloc unless
VT is
a pointer or a specialization of
reference_wrapper.copyable_function& operator=(const copyable_function& f);
Effects: Equivalent to: copyable_function(f).swap(*this);
copyable_function& operator=(copyable_function&& f);
Effects: Equivalent to: copyable_function(std::move(f)).swap(*this);
copyable_function& operator=(nullptr_t) noexcept;
Effects: Destroys the target object of
*this, if any
. template<class F> copyable_function& operator=(F&& f);
Effects: Equivalent to: copyable_function(std::forward<F>(f)).swap(*this);
Effects: Destroys the target object of
*this, if any
. explicit operator bool() const noexcept;
Returns:
true if
*this has a target object, otherwise
false. R operator()(ArgTypes... args) cv ref noexcept(noex);
Preconditions:
*this has a target object
. Effects: Equivalent to:
return INVOKE<R>(static_cast<F inv-quals>(f), std::forward<ArgTypes>(args)...);
where
f is an lvalue designating the target object of
*this and
F is the type of
f. void swap(copyable_function& other) noexcept;
Effects: Exchanges the target objects of
*this and
other. friend void swap(copyable_function& f1, copyable_function& f2) noexcept;
Effects: Equivalent to
f1.swap(f2). friend bool operator==(const copyable_function& f, nullptr_t) noexcept;
Returns:
true if
f has no target object, otherwise
false. The header provides partial specializations of
function_ref
for each combination of the possible replacements of
the placeholders
cv and
noex where:
- cv is either const or empty, and
- noex is either true or false.
namespace std {
template<class R, class... ArgTypes>
class function_ref<R(ArgTypes...) cv noexcept(noex)> {
public:
template<class F> function_ref(F*) noexcept;
template<class F> constexpr function_ref(F&&) noexcept;
template<auto f> constexpr function_ref(nontype_t<f>) noexcept;
template<auto f, class U> constexpr function_ref(nontype_t<f>, U&&) noexcept;
template<auto f, class T> constexpr function_ref(nontype_t<f>, cv T*) noexcept;
constexpr function_ref(const function_ref&) noexcept = default;
constexpr function_ref& operator=(const function_ref&) noexcept = default;
template<class T> function_ref& operator=(T) = delete;
R operator()(ArgTypes...) const noexcept(noex);
private:
template<class... T>
static constexpr bool is-invocable-using = see below;
R (*thunk-ptr)(BoundEntityType, Args&&...) noexcept(noex);
BoundEntityType bound-entity;
};
template<class F>
function_ref(F*) -> function_ref<F>;
template<auto f>
function_ref(nontype_t<f>) -> function_ref<see below>;
template<auto f, class T>
function_ref(nontype_t<f>, T&&) -> function_ref<see below>;
}
An object of class
function_ref<R(Args...) cv noexcept(noex)>
stores a pointer to function
thunk-ptr and
an object
bound-entity. bound-entity has
an unspecified trivially copyable type
BoundEntityType, that
models
copyable and
is capable of storing a pointer to object value or a pointer to function value
. The type of
thunk-ptr is
R(*)(BoundEntityType, Args&&...) noexcept(noex).Within
[func.wrap.ref],
call-args is an argument pack with elements such that
decltype((call-args))... denote
Args&&... respectively
.template<class... T>
static constexpr bool is-invocable-using = see below;
If noex is true,
is-invocable-using<T...> is equal to:
is_nothrow_invocable_r_v<R, T..., ArgTypes...>
Otherwise, is-invocable-using<T...> is equal to:
is_invocable_r_v<R, T..., ArgTypes...>
template<class F> function_ref(F* f) noexcept;
Constraints:
- is_function_v<F> is true, and
- is-invocable-using<F> is true.
Preconditions:
f is not a null pointer
. Effects: Initializes
bound-entity with
f, and
thunk-ptr with the address of a function
thunk
such that
thunk(bound-entity, call-args...)
is expression-equivalent (
[defns.expression.equivalent]) to
invoke_r<R>(f, call-args...). template<class F> constexpr function_ref(F&& f) noexcept;
Let
T be
remove_reference_t<F>.Constraints:
- remove_cvref_t<F> is not the same type as function_ref,
- is_member_pointer_v<T> is false, and
- is-invocable-using<cv T&> is true.
Effects: Initializes
bound-entity with
addressof(f), and
thunk-ptr with the address of a function
thunk
such that
thunk(bound-entity, call-args...)
is expression-equivalent (
[defns.expression.equivalent]) to
invoke_r<R>(static_cast<cv T&>(f), call-args...). template<auto f> constexpr function_ref(nontype_t<f>) noexcept;
Constraints:
is-invocable-using<F> is
true. Mandates: If
is_pointer_v<F> || is_member_pointer_v<F> is
true,
then
f != nullptr is
true. Effects: Initializes
bound-entity with a pointer to an unspecified object or
null pointer value, and
thunk-ptr with the address of a function
thunk
such that
thunk(bound-entity, call-args...)
is expression-equivalent (
[defns.expression.equivalent]) to
invoke_r<R>(f, call-args...). template<auto f, class U>
constexpr function_ref(nontype_t<f>, U&& obj) noexcept;
Let
T be
remove_reference_t<U> and
F be
decltype(f).Constraints:
- is_rvalue_reference_v<U&&> is false, and
- is-invocable-using<F, cv T&> is true.
Mandates: If
is_pointer_v<F> || is_member_pointer_v<F> is
true,
then
f != nullptr is
true. Effects: Initializes
bound-entity with
addressof(obj), and
thunk-ptr with the address of a function
thunk
such that
thunk(bound-entity, call-args...)
is expression-equivalent (
[defns.expression.equivalent]) to
invoke_r<R>(f, static_cast<cv T&>(obj), call-args...). template<auto f, class T>
constexpr function_ref(nontype_t<f>, cv T* obj) noexcept;
Constraints:
is-invocable-using<F, cv T*> is
true. Mandates: If
is_pointer_v<F> || is_member_pointer_v<F> is
true,
then
f != nullptr is
true. Preconditions: If
is_member_pointer_v<F> is
true,
obj is not a null pointer
. Effects: Initializes
bound-entity with
obj, and
thunk-ptr with the address of a function
thunk
such that
thunk(bound-entity, call-args...)
is expression-equivalent (
[defns.expression.equivalent]) to
invoke_r<R>(f, obj, call-args...). template<class T> function_ref& operator=(T) = delete;
Constraints:
- T is not the same type as function_ref,
- is_pointer_v<T> is false, and
- T is not a specialization of nontype_t.
R operator()(ArgTypes... args) const noexcept(noex);
Effects: Equivalent to:
return thunk-ptr(bound-entity, std::forward<ArgTypes>(args)...);
template<class F>
function_ref(F*) -> function_ref<F>;
Constraints:
is_function_v<F> is
true. template<auto f>
function_ref(nontype_t<f>) -> function_ref<see below>;
Let
F be
remove_pointer_t<decltype(f)>.Constraints:
is_function_v<F> is
true. Remarks: The deduced type is
function_ref<F>. template<auto f, class T>
function_ref(nontype_t<f>, T&&) -> function_ref<see below>;
Constraints:
- F is of the form
R(G::*)(A...) cv &opt noexcept(E) for a type G, or
- F is of the form
M G::* for a type G and an object type M,
in which case
let R be invoke_result_t<F, T&>,
A... be an empty pack, and
E be false, or
- F is of the form
R(*)(G, A...) noexcept(E) for a type G.
Remarks: The deduced type is
function_ref<R(A...) noexcept(E)>. Subclause
[func.search] provides function object types (
[function.objects]) for
operations that search for a sequence [
pat_first, pat_last) in another
sequence [
first, last) that is provided to the object's function call
operator
. The first sequence (the pattern to be searched for) is provided to
the object's constructor, and the second (the sequence to be searched) is
provided to the function call operator
. Template parameters named
- ForwardIterator,
- ForwardIterator1,
- ForwardIterator2,
- RandomAccessIterator,
- RandomAccessIterator1,
- RandomAccessIterator2, and
- BinaryPredicate
of templates specified in
[func.search] shall meet the same requirements and semantics as
specified in
[algorithms.general]. Template parameters named
Hash shall meet the
Cpp17Hash
requirements (Table
37)
. The Boyer-Moore searcher implements the Boyer-Moore search algorithm
. The Boyer-Moore-Horspool searcher implements the Boyer-Moore-Horspool search algorithm
. In general, the Boyer-Moore searcher will use more memory and give better runtime performance than Boyer-Moore-Horspool
.namespace std {
template<class ForwardIterator1, class BinaryPredicate = equal_to<>>
class default_searcher {
public:
constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last,
BinaryPredicate pred = BinaryPredicate());
template<class ForwardIterator2>
constexpr pair<ForwardIterator2, ForwardIterator2>
operator()(ForwardIterator2 first, ForwardIterator2 last) const;
private:
ForwardIterator1 pat_first_;
ForwardIterator1 pat_last_;
BinaryPredicate pred_;
};
}
constexpr default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last,
BinaryPredicate pred = BinaryPredicate());
Effects: Constructs a
default_searcher object, initializing
pat_first_
with
pat_first,
pat_last_ with
pat_last, and
pred_ with
pred. Throws: Any exception thrown by the copy constructor of
BinaryPredicate or
ForwardIterator1. template<class ForwardIterator2>
constexpr pair<ForwardIterator2, ForwardIterator2>
operator()(ForwardIterator2 first, ForwardIterator2 last) const;
Effects: Returns a pair of iterators
i and
j such that
- i == search(first, last, pat_first_, pat_last_, pred_), and
- if i == last, then j == last,
otherwise j == next(i, distance(pat_first_, pat_last_)).
namespace std {
template<class RandomAccessIterator1,
class Hash = hash<typename iterator_traits<RandomAccessIterator1>::value_type>,
class BinaryPredicate = equal_to<>>
class boyer_moore_searcher {
public:
boyer_moore_searcher(RandomAccessIterator1 pat_first,
RandomAccessIterator1 pat_last,
Hash hf = Hash(),
BinaryPredicate pred = BinaryPredicate());
template<class RandomAccessIterator2>
pair<RandomAccessIterator2, RandomAccessIterator2>
operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
private:
RandomAccessIterator1 pat_first_;
RandomAccessIterator1 pat_last_;
Hash hash_;
BinaryPredicate pred_;
};
}
boyer_moore_searcher(RandomAccessIterator1 pat_first,
RandomAccessIterator1 pat_last,
Hash hf = Hash(),
BinaryPredicate pred = BinaryPredicate());
Let
V be
iterator_traits<RandomAccessIterator1>::value_type. For any two values
A and
B of type
V,
if
pred(A, B) == true, then
hf(A) == hf(B) is
true.Effects: Initializes
pat_first_ with
pat_first,
pat_last_ with
pat_last,
hash_ with
hf, and
pred_ with
pred. Throws: Any exception thrown by the copy constructor of
RandomAccessIterator1,
or by the default constructor, copy constructor, or the copy assignment operator of the value type of
RandomAccessIterator1,
or the copy constructor or
operator() of
BinaryPredicate or
Hash. May throw
bad_alloc if additional memory needed for internal data structures cannot be allocated
.template<class RandomAccessIterator2>
pair<RandomAccessIterator2, RandomAccessIterator2>
operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
Mandates:
RandomAccessIterator1 and
RandomAccessIterator2
have the same value type
. Effects: Finds a subsequence of equal values in a sequence
. Returns: A pair of iterators
i and
j such that
- i is the first iterator
in the range [first, last - (pat_last_ - pat_first_)) such that
for every non-negative integer n less than pat_last_ - pat_first_
the following condition holds:
pred(*(i + n), *(pat_first_ + n)) != false, and
- j == next(i, distance(pat_first_, pat_last_)).
Returns
make_pair(first, first) if [
pat_first_, pat_last_) is empty,
otherwise returns
make_pair(last, last) if no such iterator is found
.Complexity: At most
(last - first) * (pat_last_ - pat_first_) applications of the predicate
. namespace std {
template<class RandomAccessIterator1,
class Hash = hash<typename iterator_traits<RandomAccessIterator1>::value_type>,
class BinaryPredicate = equal_to<>>
class boyer_moore_horspool_searcher {
public:
boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first,
RandomAccessIterator1 pat_last,
Hash hf = Hash(),
BinaryPredicate pred = BinaryPredicate());
template<class RandomAccessIterator2>
pair<RandomAccessIterator2, RandomAccessIterator2>
operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
private:
RandomAccessIterator1 pat_first_;
RandomAccessIterator1 pat_last_;
Hash hash_;
BinaryPredicate pred_;
};
}
boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first,
RandomAccessIterator1 pat_last,
Hash hf = Hash(),
BinaryPredicate pred = BinaryPredicate());
Let
V be
iterator_traits<RandomAccessIterator1>::value_type. For any two values
A and
B of type
V,
if
pred(A, B) == true, then
hf(A) == hf(B) is
true.Effects: Initializes
pat_first_ with
pat_first,
pat_last_ with
pat_last,
hash_ with
hf, and
pred_ with
pred. Throws: Any exception thrown by the copy constructor of
RandomAccessIterator1,
or by the default constructor, copy constructor, or the copy assignment operator of the value type of
RandomAccessIterator1,
or the copy constructor or
operator() of
BinaryPredicate or
Hash. May throw
bad_alloc if additional memory needed for internal data structures cannot be allocated
.template<class RandomAccessIterator2>
pair<RandomAccessIterator2, RandomAccessIterator2>
operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
Mandates:
RandomAccessIterator1 and
RandomAccessIterator2
have the same value type
. Effects: Finds a subsequence of equal values in a sequence
. Returns: A pair of iterators
i and
j such that
- i is the first iterator in the range
[first, last - (pat_last_ - pat_first_)) such that
for every non-negative integer n less than pat_last_ - pat_first_
the following condition holds:
pred(*(i + n), *(pat_first_ + n)) != false, and
- j == next(i, distance(pat_first_, pat_last_)).
Returns
make_pair(first, first) if [
pat_first_, pat_last_) is empty,
otherwise returns
make_pair(last, last) if no such iterator is found
.Complexity: At most
(last - first) * (pat_last_ - pat_first_) applications of the predicate
. The unordered associative containers defined in
[unord] use
specializations of the class template
hash (
[functional.syn])
as the default hash function
.Each specialization of
hash is either enabled or disabled,
as described below
. [
Note 1:
Enabled specializations meet the
Cpp17Hash requirements, and
disabled specializations do not
. —
end note]
Each header that declares the template
hash
provides enabled specializations of
hash for
nullptr_t and
all cv-unqualified arithmetic, enumeration, and pointer types
. For any type
Key for which neither the library nor the user provides
an explicit or partial specialization of the class template
hash,
hash<Key> is disabled
.If the library provides an explicit or partial specialization of
hash<Key>,
that specialization is enabled except as noted otherwise,
and its member functions are
noexcept except as noted otherwise
.If
H is a disabled specialization of
hash,
these values are
false:
is_default_constructible_v<H>,
is_copy_constructible_v<H>,
is_move_constructible_v<H>,
is_copy_assignable_v<H>, and
is_move_assignable_v<H>. [
Note 2:
This means that the specialization of
hash exists, but
any attempts to use it as a
Cpp17Hash will be ill-formed
. —
end note]
An enabled specialization
hash<Key> will:
- meet the Cpp17Hash requirements (Table 37),
with Key as the function
call argument type, the Cpp17DefaultConstructible requirements (Table 30),
the Cpp17CopyAssignable requirements (Table 34),
the Cpp17Swappable requirements ([swappable.requirements]),
- meet the requirement that if k1 == k2 is true, h(k1) == h(k2) is
also true, where h is an object of type hash<Key> and k1 and k2
are objects of type Key;
- meet the requirement that the expression h(k), where h
is an object of type hash<Key> and k is an object of type
Key, shall not throw an exception unless hash<Key> is a
program-defined specialization.
The header provides components to access,
manipulate and process both individual bits and bit sequences
.
namespace std {
template<class To, class From>
constexpr To bit_cast(const From& from) noexcept;
template<class T>
constexpr T byteswap(T value) noexcept;
template<class T>
constexpr bool has_single_bit(T x) noexcept;
template<class T>
constexpr T bit_ceil(T x);
template<class T>
constexpr T bit_floor(T x) noexcept;
template<class T>
constexpr int bit_width(T x) noexcept;
template<class T>
constexpr T rotl(T x, int s) noexcept;
template<class T>
constexpr T rotr(T x, int s) noexcept;
template<class T>
constexpr int countl_zero(T x) noexcept;
template<class T>
constexpr int countl_one(T x) noexcept;
template<class T>
constexpr int countr_zero(T x) noexcept;
template<class T>
constexpr int countr_one(T x) noexcept;
template<class T>
constexpr int popcount(T x) noexcept;
enum class endian {
little = see below,
big = see below,
native = see below
};
}
template<class To, class From>
constexpr To bit_cast(const From& from) noexcept;
Constraints:
- sizeof(To) == sizeof(From) is true;
- is_trivially_copyable_v<To> is true; and
- is_trivially_copyable_v<From> is true.
Mandates: Neither
To nor
From are consteval-only types (
[expr.const])
. Constant When:
To,
From, and the types of all subobjects
of
To and
From are types
T such that:
- is_union_v<T> is false;
- is_pointer_v<T> is false;
- is_member_pointer_v<T> is false;
- is_volatile_v<T> is false; and
- T has no non-static data members of reference type.
Returns: An object of type
To. Each bit of the value representation of the result
is equal to the corresponding bit in the object representation
of
from. Padding bits of the result are unspecified
. For the result and each object created within it,
if there is no value of the object's type corresponding to the
value representation produced, the behavior is undefined
. If there are multiple such values, which value is produced is unspecified
. A bit in the value representation of the result is indeterminate if
it does not correspond to a bit in the value representation of
from or
corresponds to a bit
for which the smallest enclosing object is not within its lifetime or
has an indeterminate value (
[basic.indet])
. A bit in the value representation of the result is erroneous
if it corresponds to a bit
for which the smallest enclosing object has an erroneous value
. For each bit
b in the value representation of the result
that is indeterminate or erroneous,
let
u be the smallest object containing that bit enclosing
b:
If
u is of unsigned ordinary character type or
std::byte type,
u has an indeterminate value
if any of the bits in its value representation are indeterminate, or
otherwise has an erroneous value
.Otherwise, if
b is indeterminate, the behavior is undefined
.Otherwise, the behavior is erroneous, and the result is as specified above
.
The result does not otherwise contain any indeterminate or erroneous values
.template<class T>
constexpr T byteswap(T value) noexcept;
Let the sequence
R comprise
the bytes of the object representation of
value in reverse order
.Returns: An object
v of type
T
such that each byte in the object representation of
v is equal to
the byte in the corresponding position in
R. template<class T>
constexpr bool has_single_bit(T x) noexcept;
Returns:
true if
x is an integral power of two;
false otherwise
. template<class T>
constexpr T bit_ceil(T x);
Let
N be the smallest power of 2 greater than or equal to
x.Preconditions:
N is representable as a value of type
T. Remarks: A function call expression
that violates the precondition in the
Preconditions: element
is not a core constant expression (
[expr.const])
. template<class T>
constexpr T bit_floor(T x) noexcept;
Returns: If
x == 0,
0;
otherwise the maximal value
y
such that
has_single_bit(y) is
true and
y <= x. template<class T>
constexpr int bit_width(T x) noexcept;
Returns: If
x == 0,
0;
otherwise one plus the base-2 logarithm of
x,
with any fractional part discarded
. In the following descriptions,
let
N denote
numeric_limits<T>::digits.template<class T>
constexpr T rotl(T x, int s) noexcept;
Returns: If
r is
0,
x;
if
r is positive,
(x << r) | (x >> (N - r));
if
r is negative,
rotr(x, -r). template<class T>
constexpr T rotr(T x, int s) noexcept;
Returns: If
r is
0,
x;
if
r is positive,
(x >> r) | (x << (N - r));
if
r is negative,
rotl(x, -r). In the following descriptions,
let
N denote
numeric_limits<T>::digits.template<class T>
constexpr int countl_zero(T x) noexcept;
Returns: The number of consecutive
0 bits in the value of
x,
starting from the most significant bit
. template<class T>
constexpr int countl_one(T x) noexcept;
Returns: The number of consecutive
1 bits in the value of
x,
starting from the most significant bit
. [
Note 2:
Returns
N if
x == numeric_limits<T>::max(). —
end note]
template<class T>
constexpr int countr_zero(T x) noexcept;
Returns: The number of consecutive
0 bits in the value of
x,
starting from the least significant bit
. template<class T>
constexpr int countr_one(T x) noexcept;
Returns: The number of consecutive
1 bits in the value of
x,
starting from the least significant bit
. [
Note 4:
Returns
N if
x == numeric_limits<T>::max(). —
end note]
template<class T>
constexpr int popcount(T x) noexcept;
Returns: The number of
1 bits in the value of
x. Two common methods of byte ordering in multibyte scalar types are big-endian
and little-endian in the execution environment
. Big-endian is a format for
storage of binary data in which the most significant byte is placed first,
with the rest in descending order
. Little-endian is a format for storage of
binary data in which the least significant byte is placed first, with the rest
in ascending order
. This subclause describes the endianness of the scalar types
of the execution environment
.enum class endian {
little = see below,
big = see below,
native = see below
};
If all scalar types have size 1 byte, then all of
endian::little,
endian::big, and
endian::native have the same value
. Otherwise,
endian::little is not equal to
endian::big. If all scalar types are big-endian,
endian::native is
equal to
endian::big. If all scalar types are little-endian,
endian::native is
equal to
endian::little. Otherwise,
endian::native is not equal
to either
endian::big or
endian::little.For a function template whose return type is not specified above,
the return type is
an
implementation-defined unsigned integer type
large enough to represent all possible result values
. Each function template has the same semantics
as the corresponding type-generic function with the same name
specified in ISO/IEC 9899:2024, 7.18
.Mandates:
T is an unsigned integer type
. Otherwise,
the contents and meaning of the header
are the same as
the C standard library header
<stdbit.h>.See also: ISO/IEC 9899:2024, 7.18