tmp/tmpj4ia0jem/{from.md → to.md}
RENAMED
|
@@ -1,17 +1,21 @@
|
|
| 1 |
## Tuples <a id="tuple">[[tuple]]</a>
|
| 2 |
|
| 3 |
-
###
|
| 4 |
|
| 5 |
Subclause [[tuple]] describes the tuple library that provides a tuple
|
| 6 |
type as the class template `tuple` that can be instantiated with any
|
| 7 |
number of arguments. Each template argument specifies the type of an
|
| 8 |
element in the `tuple`. Consequently, tuples are heterogeneous,
|
| 9 |
fixed-size collections of values. An instantiation of `tuple` with two
|
| 10 |
arguments is similar to an instantiation of `pair` with the same two
|
| 11 |
arguments. See [[pairs]].
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
### Header `<tuple>` synopsis <a id="tuple.syn">[[tuple.syn]]</a>
|
| 14 |
|
| 15 |
``` cpp
|
| 16 |
// all freestanding
|
| 17 |
#include <compare> // see [compare.syn]
|
|
@@ -33,13 +37,18 @@ namespace std {
|
|
| 33 |
template<class> class TQual, template<class> class UQual>
|
| 34 |
struct basic_common_reference<TTuple, UTuple, TQual, UQual>;
|
| 35 |
template<exposition onlyconceptnc{tuple-like} TTuple, exposition onlyconceptnc{tuple-like} UTuple>
|
| 36 |
struct common_type<TTuple, UTuple>;
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
// [tuple.creation], tuple creation functions
|
| 39 |
-
inline constexpr unspecified ignore;
|
| 40 |
-
|
| 41 |
template<class... TTypes>
|
| 42 |
constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&...);
|
| 43 |
|
| 44 |
template<class... TTypes>
|
| 45 |
constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept;
|
|
@@ -50,11 +59,12 @@ namespace std {
|
|
| 50 |
template<exposition onlyconceptnc{tuple-like}... Tuples>
|
| 51 |
constexpr tuple<CTypes...> tuple_cat(Tuples&&...);
|
| 52 |
|
| 53 |
// [tuple.apply], calling a function with a tuple of arguments
|
| 54 |
template<class F, exposition onlyconceptnc{tuple-like} Tuple>
|
| 55 |
-
constexpr
|
|
|
|
| 56 |
|
| 57 |
template<class T, exposition onlyconceptnc{tuple-like} Tuple>
|
| 58 |
constexpr T make_from_tuple(Tuple&& t);
|
| 59 |
|
| 60 |
// [tuple.helper], tuple helper classes
|
|
@@ -68,11 +78,11 @@ namespace std {
|
|
| 68 |
|
| 69 |
template<size_t I, class... Types>
|
| 70 |
struct tuple_element<I, tuple<Types...>>;
|
| 71 |
|
| 72 |
template<size_t I, class T>
|
| 73 |
-
using tuple_element_t =
|
| 74 |
|
| 75 |
// [tuple.elem], element access
|
| 76 |
template<size_t I, class... Types>
|
| 77 |
constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>&) noexcept;
|
| 78 |
template<size_t I, class... Types>
|
|
@@ -123,15 +133,17 @@ namespace std {
|
|
| 123 |
template<class T>
|
| 124 |
concept tuple-like = see belownc; // exposition only
|
| 125 |
```
|
| 126 |
|
| 127 |
A type `T` models and satisfies the exposition-only concept `tuple-like`
|
| 128 |
-
if `remove_cvref_t<T>` is a specialization of `array`, `
|
| 129 |
-
or `ranges::subrange`.
|
| 130 |
|
| 131 |
### Class template `tuple` <a id="tuple.tuple">[[tuple.tuple]]</a>
|
| 132 |
|
|
|
|
|
|
|
| 133 |
``` cpp
|
| 134 |
namespace std {
|
| 135 |
template<class... Types>
|
| 136 |
class tuple {
|
| 137 |
public:
|
|
@@ -253,10 +265,13 @@ namespace std {
|
|
| 253 |
template<class Alloc, class... UTypes>
|
| 254 |
tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>;
|
| 255 |
}
|
| 256 |
```
|
| 257 |
|
|
|
|
|
|
|
|
|
|
| 258 |
#### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
|
| 259 |
|
| 260 |
In the descriptions that follow, let i be in the range \[`0`,
|
| 261 |
`sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`, and `Uᵢ`
|
| 262 |
be the iᵗʰ type in a template parameter pack named `UTypes`, where
|
|
@@ -367,11 +382,11 @@ template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&
|
|
| 367 |
template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u);
|
| 368 |
template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u);
|
| 369 |
template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>&& u);
|
| 370 |
```
|
| 371 |
|
| 372 |
-
Let `I` be the pack `0, 1,
|
| 373 |
*`FWD`*`(u)` be `static_cast<decltype(u)>(u)`.
|
| 374 |
|
| 375 |
*Constraints:*
|
| 376 |
|
| 377 |
- `sizeof...(Types)` equals `sizeof...(UTypes)`, and
|
|
@@ -438,21 +453,21 @@ is `true`.
|
|
| 438 |
``` cpp
|
| 439 |
template<tuple-like UTuple>
|
| 440 |
constexpr explicit(see below) tuple(UTuple&& u);
|
| 441 |
```
|
| 442 |
|
| 443 |
-
Let `I` be the pack `0, 1, …, (sizeof...(Types) - 1)`.
|
| 444 |
|
| 445 |
*Constraints:*
|
| 446 |
|
| 447 |
- `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
|
| 448 |
- `remove_cvref_t<UTuple>` is not a specialization of
|
| 449 |
`ranges::subrange`,
|
| 450 |
- `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`,
|
| 451 |
- `(is_constructible_v<Types, decltype(get<I>(std::forward<UTuple>(u)))> && ...)`
|
| 452 |
is `true`, and
|
| 453 |
-
- either `sizeof...(Types)` is not
|
| 454 |
`T`) `is_convertible_v<UTuple, T>` and `is_constructible_v<T, UTuple>`
|
| 455 |
are both `false`.
|
| 456 |
|
| 457 |
*Effects:* For all i, initializes the iᵗʰ element of `*this` with
|
| 458 |
`get<`i`>(std::forward<UTuple>(u))`.
|
|
@@ -461,10 +476,19 @@ Let `I` be the pack `0, 1, …, (sizeof...(Types) - 1)`.
|
|
| 461 |
|
| 462 |
``` cpp
|
| 463 |
!(is_convertible_v<decltype(get<I>(std::forward<UTuple>(u))), Types> && ...)
|
| 464 |
```
|
| 465 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 466 |
``` cpp
|
| 467 |
template<class Alloc>
|
| 468 |
constexpr explicit(see below)
|
| 469 |
tuple(allocator_arg_t, const Alloc& a);
|
| 470 |
template<class Alloc>
|
|
@@ -703,11 +727,11 @@ template<tuple-like UTuple>
|
|
| 703 |
*Constraints:*
|
| 704 |
|
| 705 |
- `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
|
| 706 |
- `remove_cvref_t<UTuple>` is not a specialization of
|
| 707 |
`ranges::subrange`,
|
| 708 |
-
- `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`, and
|
| 709 |
- `is_assignable_v<``Tᵢ``&, decltype(get<`i`>(std::forward<UTuple>(u)))>`
|
| 710 |
is `true` for all i.
|
| 711 |
|
| 712 |
*Effects:* For all i, assigns `get<`i`>(std::forward<UTuple>(u))` to
|
| 713 |
`get<`i`>(*this)`.
|
|
@@ -722,11 +746,11 @@ template<tuple-like UTuple>
|
|
| 722 |
*Constraints:*
|
| 723 |
|
| 724 |
- `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
|
| 725 |
- `remove_cvref_t<UTuple>` is not a specialization of
|
| 726 |
`ranges::subrange`,
|
| 727 |
-
- `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`, and
|
| 728 |
- `is_assignable_v<const ``Tᵢ``&, decltype(get<`i`>(std::forward<UTuple>(u)))>`
|
| 729 |
is `true` for all i.
|
| 730 |
|
| 731 |
*Effects:* For all i, assigns `get<`i`>(std::forward<UTuple>(u))` to
|
| 732 |
`get<`i`>(*this)`.
|
|
@@ -749,11 +773,11 @@ Let i be in the range \[`0`, `sizeof...(Types)`) in order.
|
|
| 749 |
`true`.
|
| 750 |
|
| 751 |
*Preconditions:* For all i, `get<`i`>(*this)` is swappable
|
| 752 |
with [[swappable.requirements]] `get<`i`>(rhs)`.
|
| 753 |
|
| 754 |
-
*Effects:* For each i, calls `swap` for `get<`i`>(*this)`
|
| 755 |
`get<`i`>(rhs)`.
|
| 756 |
|
| 757 |
*Throws:* Nothing unless one of the element-wise `swap` calls throws an
|
| 758 |
exception.
|
| 759 |
|
|
@@ -801,13 +825,11 @@ variable).
|
|
| 801 |
``` cpp
|
| 802 |
template<class... TTypes>
|
| 803 |
constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
|
| 804 |
```
|
| 805 |
|
| 806 |
-
*Returns:* `tuple<TTypes&...>(t...)`.
|
| 807 |
-
`ignore`, assigning any value to the corresponding tuple element has no
|
| 808 |
-
effect.
|
| 809 |
|
| 810 |
[*Example 2*:
|
| 811 |
|
| 812 |
`tie` functions allow one to create tuples that unpack tuples into
|
| 813 |
variables. `ignore` can be used for elements that are not needed:
|
|
@@ -849,14 +871,15 @@ elems₀`...`, …, elemsₙ₋₁`...`.
|
|
| 849 |
|
| 850 |
### Calling a function with a `tuple` of arguments <a id="tuple.apply">[[tuple.apply]]</a>
|
| 851 |
|
| 852 |
``` cpp
|
| 853 |
template<class F, tuple-like Tuple>
|
| 854 |
-
constexpr
|
|
|
|
| 855 |
```
|
| 856 |
|
| 857 |
-
*Effects:* Given the exposition-only function:
|
| 858 |
|
| 859 |
``` cpp
|
| 860 |
namespace std {
|
| 861 |
template<class F, tuple-like Tuple, size_t... I>
|
| 862 |
constexpr decltype(auto) apply-impl(F&& f, Tuple&& t, index_sequence<I...>) {
|
|
@@ -871,28 +894,20 @@ Equivalent to:
|
|
| 871 |
``` cpp
|
| 872 |
return apply-impl(std::forward<F>(f), std::forward<Tuple>(t),
|
| 873 |
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
|
| 874 |
```
|
| 875 |
|
| 876 |
-
*Remarks:* Let `I` be the pack
|
| 877 |
-
`0, 1, ..., (tuple_size_v<remove_reference_t<Tuple>> - 1)`. The
|
| 878 |
-
exception specification is equivalent to:
|
| 879 |
-
|
| 880 |
-
``` cpp
|
| 881 |
-
noexcept(invoke(std::forward<F>(f), get<I>(std::forward<Tuple>(t))...))
|
| 882 |
-
```
|
| 883 |
-
|
| 884 |
``` cpp
|
| 885 |
template<class T, tuple-like Tuple>
|
| 886 |
constexpr T make_from_tuple(Tuple&& t);
|
| 887 |
```
|
| 888 |
|
| 889 |
*Mandates:* If `tuple_size_v<remove_reference_t<Tuple>>` is 1, then
|
| 890 |
`reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))>`
|
| 891 |
is `false`.
|
| 892 |
|
| 893 |
-
*Effects:* Given the exposition-only function:
|
| 894 |
|
| 895 |
``` cpp
|
| 896 |
namespace std {
|
| 897 |
template<class T, tuple-like Tuple, size_t... I>
|
| 898 |
requires is_constructible_v<T, decltype(get<I>(declval<Tuple>()))...>
|
|
@@ -918,17 +933,17 @@ list. — *end note*]
|
|
| 918 |
|
| 919 |
``` cpp
|
| 920 |
template<class T> struct tuple_size;
|
| 921 |
```
|
| 922 |
|
| 923 |
-
|
| 924 |
-
requirements [[meta.rqmts]] with a base
|
| 925 |
-
`integral_constant<size_t, N>` for some `N`.
|
| 926 |
|
| 927 |
``` cpp
|
| 928 |
template<class... Types>
|
| 929 |
-
struct tuple_size<tuple<Types...>> :
|
| 930 |
```
|
| 931 |
|
| 932 |
``` cpp
|
| 933 |
template<size_t I, class... Types>
|
| 934 |
struct tuple_element<I, tuple<Types...>> {
|
|
@@ -936,12 +951,12 @@ template<size_t I, class... Types>
|
|
| 936 |
};
|
| 937 |
```
|
| 938 |
|
| 939 |
*Mandates:* `I` < `sizeof...(Types)`.
|
| 940 |
|
| 941 |
-
*
|
| 942 |
-
is zero-based.
|
| 943 |
|
| 944 |
``` cpp
|
| 945 |
template<class T> struct tuple_size<const T>;
|
| 946 |
```
|
| 947 |
|
|
@@ -976,11 +991,11 @@ template<size_t I, class T> struct tuple_element<I, const T>;
|
|
| 976 |
```
|
| 977 |
|
| 978 |
Let `TE` denote `tuple_element_t<I, T>` of the cv-unqualified type `T`.
|
| 979 |
Then each specialization of the template meets the
|
| 980 |
*Cpp17TransformationTrait* requirements [[meta.rqmts]] with a member
|
| 981 |
-
typedef `type` that names the type `
|
| 982 |
|
| 983 |
In addition to being available via inclusion of the `<tuple>` header,
|
| 984 |
the template is available when any of the headers `<array>`, `<ranges>`,
|
| 985 |
or `<utility>` are included.
|
| 986 |
|
|
@@ -990,32 +1005,34 @@ or `<utility>` are included.
|
|
| 990 |
template<size_t I, class... Types>
|
| 991 |
constexpr tuple_element_t<I, tuple<Types...>>&
|
| 992 |
get(tuple<Types...>& t) noexcept;
|
| 993 |
template<size_t I, class... Types>
|
| 994 |
constexpr tuple_element_t<I, tuple<Types...>>&&
|
| 995 |
-
get(tuple<Types...>&& t) noexcept; //
|
| 996 |
template<size_t I, class... Types>
|
| 997 |
constexpr const tuple_element_t<I, tuple<Types...>>&
|
| 998 |
-
get(const tuple<Types...>& t) noexcept; //
|
| 999 |
template<size_t I, class... Types>
|
| 1000 |
constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
|
| 1001 |
```
|
| 1002 |
|
| 1003 |
*Mandates:* `I` < `sizeof...(Types)`.
|
| 1004 |
|
| 1005 |
*Returns:* A reference to the `I`ᵗʰ element of `t`, where indexing is
|
| 1006 |
zero-based.
|
| 1007 |
|
| 1008 |
-
[*Note 1*:
|
| 1009 |
-
`X&`, the return type is `X&`, not `X&&`. However,
|
| 1010 |
-
is a non-reference type `T`, the return type is
|
|
|
|
| 1011 |
|
| 1012 |
-
[*Note 2*:
|
| 1013 |
-
some reference type `X&`, the return type is `X&`, not
|
| 1014 |
-
However, if the element type is a non-reference type `T`,
|
| 1015 |
-
type is `const T&`. This is consistent with how constness is
|
| 1016 |
-
work for non-static data members of reference
|
|
|
|
| 1017 |
|
| 1018 |
``` cpp
|
| 1019 |
template<class T, class... Types>
|
| 1020 |
constexpr T& get(tuple<Types...>& t) noexcept;
|
| 1021 |
template<class T, class... Types>
|
|
@@ -1056,16 +1073,14 @@ template<class... TTypes, tuple-like UTuple>
|
|
| 1056 |
constexpr bool operator==(const tuple<TTypes...>& t, const UTuple& u);
|
| 1057 |
```
|
| 1058 |
|
| 1059 |
For the first overload let `UTuple` be `tuple<UTypes...>`.
|
| 1060 |
|
| 1061 |
-
*
|
| 1062 |
-
`get<i>(t) == get<i>(u)` is a valid expression
|
| 1063 |
-
|
| 1064 |
-
|
| 1065 |
-
*Preconditions:* For all `i`, `decltype(get<i>(t) == get<i>(u))` models
|
| 1066 |
-
`boolean-testable`.
|
| 1067 |
|
| 1068 |
*Returns:* `true` if `get<i>(t) == get<i>(u)` for all `i`, otherwise
|
| 1069 |
`false`.
|
| 1070 |
|
| 1071 |
[*Note 1*: If `sizeof...(TTypes)` equals zero, returns
|
|
@@ -1109,11 +1124,11 @@ lookup [[basic.lookup.argdep]] only.
|
|
| 1109 |
|
| 1110 |
[*Note 1*: The above definition does not require `tₜₐᵢₗ` (or `uₜₐᵢₗ`)
|
| 1111 |
to be constructed. It might not even be possible, as `t` and `u` are not
|
| 1112 |
required to be copy constructible. Also, all comparison operator
|
| 1113 |
functions are short circuited; they do not perform element accesses
|
| 1114 |
-
beyond what is
|
| 1115 |
comparison. — *end note*]
|
| 1116 |
|
| 1117 |
### `common_reference` related specializations <a id="tuple.common.ref">[[tuple.common.ref]]</a>
|
| 1118 |
|
| 1119 |
In the descriptions that follow:
|
|
@@ -1141,11 +1156,11 @@ struct basic_common_reference<TTuple, UTuple, TQual, UQual> {
|
|
| 1141 |
- `is_same_v<UTuple, decay_t<UTuple>>` is `true`.
|
| 1142 |
- `tuple_size_v<TTuple>` equals `tuple_size_v<UTuple>`.
|
| 1143 |
- `tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>` denotes a
|
| 1144 |
type.
|
| 1145 |
|
| 1146 |
-
The member *typedef-name* `type` denotes the type
|
| 1147 |
`tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>`.
|
| 1148 |
|
| 1149 |
``` cpp
|
| 1150 |
template<tuple-like TTuple, tuple-like UTuple>
|
| 1151 |
struct common_type<TTuple, UTuple> {
|
|
@@ -1160,11 +1175,11 @@ struct common_type<TTuple, UTuple> {
|
|
| 1160 |
- `is_same_v<TTuple, decay_t<TTuple>>` is `true`.
|
| 1161 |
- `is_same_v<UTuple, decay_t<UTuple>>` is `true`.
|
| 1162 |
- `tuple_size_v<TTuple>` equals `tuple_size_v<UTuple>`.
|
| 1163 |
- `tuple<common_type_t<TTypes, UTypes>...>` denotes a type.
|
| 1164 |
|
| 1165 |
-
The member *typedef-name* `type` denotes the type
|
| 1166 |
`tuple<common_type_t<TTypes, UTypes>...>`.
|
| 1167 |
|
| 1168 |
### Tuple traits <a id="tuple.traits">[[tuple.traits]]</a>
|
| 1169 |
|
| 1170 |
``` cpp
|
|
|
|
| 1 |
## Tuples <a id="tuple">[[tuple]]</a>
|
| 2 |
|
| 3 |
+
### General <a id="tuple.general">[[tuple.general]]</a>
|
| 4 |
|
| 5 |
Subclause [[tuple]] describes the tuple library that provides a tuple
|
| 6 |
type as the class template `tuple` that can be instantiated with any
|
| 7 |
number of arguments. Each template argument specifies the type of an
|
| 8 |
element in the `tuple`. Consequently, tuples are heterogeneous,
|
| 9 |
fixed-size collections of values. An instantiation of `tuple` with two
|
| 10 |
arguments is similar to an instantiation of `pair` with the same two
|
| 11 |
arguments. See [[pairs]].
|
| 12 |
|
| 13 |
+
In addition to being available via inclusion of the `<tuple>` header,
|
| 14 |
+
`ignore` [[tuple.syn]] is available when `<utility>` [[utility]] is
|
| 15 |
+
included.
|
| 16 |
+
|
| 17 |
### Header `<tuple>` synopsis <a id="tuple.syn">[[tuple.syn]]</a>
|
| 18 |
|
| 19 |
``` cpp
|
| 20 |
// all freestanding
|
| 21 |
#include <compare> // see [compare.syn]
|
|
|
|
| 37 |
template<class> class TQual, template<class> class UQual>
|
| 38 |
struct basic_common_reference<TTuple, UTuple, TQual, UQual>;
|
| 39 |
template<exposition onlyconceptnc{tuple-like} TTuple, exposition onlyconceptnc{tuple-like} UTuple>
|
| 40 |
struct common_type<TTuple, UTuple>;
|
| 41 |
|
| 42 |
+
// ignore
|
| 43 |
+
struct ignore-type { // exposition only
|
| 44 |
+
constexpr const ignore-type&
|
| 45 |
+
operator=(const auto &) const noexcept { return *this; }
|
| 46 |
+
};
|
| 47 |
+
inline constexpr ignore-type ignore;
|
| 48 |
+
|
| 49 |
// [tuple.creation], tuple creation functions
|
|
|
|
|
|
|
| 50 |
template<class... TTypes>
|
| 51 |
constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&...);
|
| 52 |
|
| 53 |
template<class... TTypes>
|
| 54 |
constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept;
|
|
|
|
| 59 |
template<exposition onlyconceptnc{tuple-like}... Tuples>
|
| 60 |
constexpr tuple<CTypes...> tuple_cat(Tuples&&...);
|
| 61 |
|
| 62 |
// [tuple.apply], calling a function with a tuple of arguments
|
| 63 |
template<class F, exposition onlyconceptnc{tuple-like} Tuple>
|
| 64 |
+
constexpr apply_result_t<F, Tuple> apply(F&& f, Tuple&& t)
|
| 65 |
+
noexcept(is_nothrow_applicable_v<F, Tuple>);
|
| 66 |
|
| 67 |
template<class T, exposition onlyconceptnc{tuple-like} Tuple>
|
| 68 |
constexpr T make_from_tuple(Tuple&& t);
|
| 69 |
|
| 70 |
// [tuple.helper], tuple helper classes
|
|
|
|
| 78 |
|
| 79 |
template<size_t I, class... Types>
|
| 80 |
struct tuple_element<I, tuple<Types...>>;
|
| 81 |
|
| 82 |
template<size_t I, class T>
|
| 83 |
+
using tuple_element_t = tuple_element<I, T>::type;
|
| 84 |
|
| 85 |
// [tuple.elem], element access
|
| 86 |
template<size_t I, class... Types>
|
| 87 |
constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>&) noexcept;
|
| 88 |
template<size_t I, class... Types>
|
|
|
|
| 133 |
template<class T>
|
| 134 |
concept tuple-like = see belownc; // exposition only
|
| 135 |
```
|
| 136 |
|
| 137 |
A type `T` models and satisfies the exposition-only concept `tuple-like`
|
| 138 |
+
if `remove_cvref_t<T>` is a specialization of `array`, `complex`,
|
| 139 |
+
`pair`, `tuple`, or `ranges::subrange`.
|
| 140 |
|
| 141 |
### Class template `tuple` <a id="tuple.tuple">[[tuple.tuple]]</a>
|
| 142 |
|
| 143 |
+
#### General <a id="tuple.tuple.general">[[tuple.tuple.general]]</a>
|
| 144 |
+
|
| 145 |
``` cpp
|
| 146 |
namespace std {
|
| 147 |
template<class... Types>
|
| 148 |
class tuple {
|
| 149 |
public:
|
|
|
|
| 265 |
template<class Alloc, class... UTypes>
|
| 266 |
tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>;
|
| 267 |
}
|
| 268 |
```
|
| 269 |
|
| 270 |
+
If a program declares an explicit or partial specialization of `tuple`,
|
| 271 |
+
the program is ill-formed, no diagnostic required.
|
| 272 |
+
|
| 273 |
#### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
|
| 274 |
|
| 275 |
In the descriptions that follow, let i be in the range \[`0`,
|
| 276 |
`sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`, and `Uᵢ`
|
| 277 |
be the iᵗʰ type in a template parameter pack named `UTypes`, where
|
|
|
|
| 382 |
template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u);
|
| 383 |
template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u);
|
| 384 |
template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>&& u);
|
| 385 |
```
|
| 386 |
|
| 387 |
+
Let `I` be the pack `0, 1, `…`, (sizeof...(Types) - 1)`. Let
|
| 388 |
*`FWD`*`(u)` be `static_cast<decltype(u)>(u)`.
|
| 389 |
|
| 390 |
*Constraints:*
|
| 391 |
|
| 392 |
- `sizeof...(Types)` equals `sizeof...(UTypes)`, and
|
|
|
|
| 453 |
``` cpp
|
| 454 |
template<tuple-like UTuple>
|
| 455 |
constexpr explicit(see below) tuple(UTuple&& u);
|
| 456 |
```
|
| 457 |
|
| 458 |
+
Let `I` be the pack `0, 1, `…`, (sizeof...(Types) - 1)`.
|
| 459 |
|
| 460 |
*Constraints:*
|
| 461 |
|
| 462 |
- `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
|
| 463 |
- `remove_cvref_t<UTuple>` is not a specialization of
|
| 464 |
`ranges::subrange`,
|
| 465 |
- `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`,
|
| 466 |
- `(is_constructible_v<Types, decltype(get<I>(std::forward<UTuple>(u)))> && ...)`
|
| 467 |
is `true`, and
|
| 468 |
+
- either `sizeof...(Types)` is not 1, or (when `Types...` expands to
|
| 469 |
`T`) `is_convertible_v<UTuple, T>` and `is_constructible_v<T, UTuple>`
|
| 470 |
are both `false`.
|
| 471 |
|
| 472 |
*Effects:* For all i, initializes the iᵗʰ element of `*this` with
|
| 473 |
`get<`i`>(std::forward<UTuple>(u))`.
|
|
|
|
| 476 |
|
| 477 |
``` cpp
|
| 478 |
!(is_convertible_v<decltype(get<I>(std::forward<UTuple>(u))), Types> && ...)
|
| 479 |
```
|
| 480 |
|
| 481 |
+
The constructor is defined as deleted if
|
| 482 |
+
|
| 483 |
+
``` cpp
|
| 484 |
+
(reference_constructs_from_temporary_v<Types, decltype(get<I>(std::forward<UTuple>(u)))>
|
| 485 |
+
|| ...)
|
| 486 |
+
```
|
| 487 |
+
|
| 488 |
+
is `true`.
|
| 489 |
+
|
| 490 |
``` cpp
|
| 491 |
template<class Alloc>
|
| 492 |
constexpr explicit(see below)
|
| 493 |
tuple(allocator_arg_t, const Alloc& a);
|
| 494 |
template<class Alloc>
|
|
|
|
| 727 |
*Constraints:*
|
| 728 |
|
| 729 |
- `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
|
| 730 |
- `remove_cvref_t<UTuple>` is not a specialization of
|
| 731 |
`ranges::subrange`,
|
| 732 |
+
- `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`, and
|
| 733 |
- `is_assignable_v<``Tᵢ``&, decltype(get<`i`>(std::forward<UTuple>(u)))>`
|
| 734 |
is `true` for all i.
|
| 735 |
|
| 736 |
*Effects:* For all i, assigns `get<`i`>(std::forward<UTuple>(u))` to
|
| 737 |
`get<`i`>(*this)`.
|
|
|
|
| 746 |
*Constraints:*
|
| 747 |
|
| 748 |
- `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
|
| 749 |
- `remove_cvref_t<UTuple>` is not a specialization of
|
| 750 |
`ranges::subrange`,
|
| 751 |
+
- `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`, and
|
| 752 |
- `is_assignable_v<const ``Tᵢ``&, decltype(get<`i`>(std::forward<UTuple>(u)))>`
|
| 753 |
is `true` for all i.
|
| 754 |
|
| 755 |
*Effects:* For all i, assigns `get<`i`>(std::forward<UTuple>(u))` to
|
| 756 |
`get<`i`>(*this)`.
|
|
|
|
| 773 |
`true`.
|
| 774 |
|
| 775 |
*Preconditions:* For all i, `get<`i`>(*this)` is swappable
|
| 776 |
with [[swappable.requirements]] `get<`i`>(rhs)`.
|
| 777 |
|
| 778 |
+
*Effects:* For each i, calls `swap` for `get<`i`>(*this)` and
|
| 779 |
`get<`i`>(rhs)`.
|
| 780 |
|
| 781 |
*Throws:* Nothing unless one of the element-wise `swap` calls throws an
|
| 782 |
exception.
|
| 783 |
|
|
|
|
| 825 |
``` cpp
|
| 826 |
template<class... TTypes>
|
| 827 |
constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
|
| 828 |
```
|
| 829 |
|
| 830 |
+
*Returns:* `tuple<TTypes&...>(t...)`.
|
|
|
|
|
|
|
| 831 |
|
| 832 |
[*Example 2*:
|
| 833 |
|
| 834 |
`tie` functions allow one to create tuples that unpack tuples into
|
| 835 |
variables. `ignore` can be used for elements that are not needed:
|
|
|
|
| 871 |
|
| 872 |
### Calling a function with a `tuple` of arguments <a id="tuple.apply">[[tuple.apply]]</a>
|
| 873 |
|
| 874 |
``` cpp
|
| 875 |
template<class F, tuple-like Tuple>
|
| 876 |
+
constexpr apply_result_t<F, Tuple> apply(F&& f, Tuple&& t)
|
| 877 |
+
noexcept(is_nothrow_applicable_v<F, Tuple>);
|
| 878 |
```
|
| 879 |
|
| 880 |
+
*Effects:* Given the exposition-only function template:
|
| 881 |
|
| 882 |
``` cpp
|
| 883 |
namespace std {
|
| 884 |
template<class F, tuple-like Tuple, size_t... I>
|
| 885 |
constexpr decltype(auto) apply-impl(F&& f, Tuple&& t, index_sequence<I...>) {
|
|
|
|
| 894 |
``` cpp
|
| 895 |
return apply-impl(std::forward<F>(f), std::forward<Tuple>(t),
|
| 896 |
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
|
| 897 |
```
|
| 898 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 899 |
``` cpp
|
| 900 |
template<class T, tuple-like Tuple>
|
| 901 |
constexpr T make_from_tuple(Tuple&& t);
|
| 902 |
```
|
| 903 |
|
| 904 |
*Mandates:* If `tuple_size_v<remove_reference_t<Tuple>>` is 1, then
|
| 905 |
`reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))>`
|
| 906 |
is `false`.
|
| 907 |
|
| 908 |
+
*Effects:* Given the exposition-only function template:
|
| 909 |
|
| 910 |
``` cpp
|
| 911 |
namespace std {
|
| 912 |
template<class T, tuple-like Tuple, size_t... I>
|
| 913 |
requires is_constructible_v<T, decltype(get<I>(declval<Tuple>()))...>
|
|
|
|
| 933 |
|
| 934 |
``` cpp
|
| 935 |
template<class T> struct tuple_size;
|
| 936 |
```
|
| 937 |
|
| 938 |
+
Except where specified otherwise, all specializations of `tuple_size`
|
| 939 |
+
meet the *Cpp17UnaryTypeTrait* requirements [[meta.rqmts]] with a base
|
| 940 |
+
characteristic of `integral_constant<size_t, N>` for some `N`.
|
| 941 |
|
| 942 |
``` cpp
|
| 943 |
template<class... Types>
|
| 944 |
+
struct tuple_size<tuple<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
|
| 945 |
```
|
| 946 |
|
| 947 |
``` cpp
|
| 948 |
template<size_t I, class... Types>
|
| 949 |
struct tuple_element<I, tuple<Types...>> {
|
|
|
|
| 951 |
};
|
| 952 |
```
|
| 953 |
|
| 954 |
*Mandates:* `I` < `sizeof...(Types)`.
|
| 955 |
|
| 956 |
+
*Result:* `TI` is the type of the `I`ᵗʰ element of `Types`, where
|
| 957 |
+
indexing is zero-based.
|
| 958 |
|
| 959 |
``` cpp
|
| 960 |
template<class T> struct tuple_size<const T>;
|
| 961 |
```
|
| 962 |
|
|
|
|
| 991 |
```
|
| 992 |
|
| 993 |
Let `TE` denote `tuple_element_t<I, T>` of the cv-unqualified type `T`.
|
| 994 |
Then each specialization of the template meets the
|
| 995 |
*Cpp17TransformationTrait* requirements [[meta.rqmts]] with a member
|
| 996 |
+
typedef `type` that names the type `const TE`.
|
| 997 |
|
| 998 |
In addition to being available via inclusion of the `<tuple>` header,
|
| 999 |
the template is available when any of the headers `<array>`, `<ranges>`,
|
| 1000 |
or `<utility>` are included.
|
| 1001 |
|
|
|
|
| 1005 |
template<size_t I, class... Types>
|
| 1006 |
constexpr tuple_element_t<I, tuple<Types...>>&
|
| 1007 |
get(tuple<Types...>& t) noexcept;
|
| 1008 |
template<size_t I, class... Types>
|
| 1009 |
constexpr tuple_element_t<I, tuple<Types...>>&&
|
| 1010 |
+
get(tuple<Types...>&& t) noexcept; // #1
|
| 1011 |
template<size_t I, class... Types>
|
| 1012 |
constexpr const tuple_element_t<I, tuple<Types...>>&
|
| 1013 |
+
get(const tuple<Types...>& t) noexcept; // #2
|
| 1014 |
template<size_t I, class... Types>
|
| 1015 |
constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
|
| 1016 |
```
|
| 1017 |
|
| 1018 |
*Mandates:* `I` < `sizeof...(Types)`.
|
| 1019 |
|
| 1020 |
*Returns:* A reference to the `I`ᵗʰ element of `t`, where indexing is
|
| 1021 |
zero-based.
|
| 1022 |
|
| 1023 |
+
[*Note 1*: For the overload marked \#1, if a type `T` in `Types` is
|
| 1024 |
+
some reference type `X&`, the return type is `X&`, not `X&&`. However,
|
| 1025 |
+
if the element type is a non-reference type `T`, the return type is
|
| 1026 |
+
`T&&`. — *end note*]
|
| 1027 |
|
| 1028 |
+
[*Note 2*: Constness is shallow. For the overload marked \#2, if a type
|
| 1029 |
+
`T` in `Types` is some reference type `X&`, the return type is `X&`, not
|
| 1030 |
+
`const X&`. However, if the element type is a non-reference type `T`,
|
| 1031 |
+
the return type is `const T&`. This is consistent with how constness is
|
| 1032 |
+
defined to work for non-static data members of reference
|
| 1033 |
+
type. — *end note*]
|
| 1034 |
|
| 1035 |
``` cpp
|
| 1036 |
template<class T, class... Types>
|
| 1037 |
constexpr T& get(tuple<Types...>& t) noexcept;
|
| 1038 |
template<class T, class... Types>
|
|
|
|
| 1073 |
constexpr bool operator==(const tuple<TTypes...>& t, const UTuple& u);
|
| 1074 |
```
|
| 1075 |
|
| 1076 |
For the first overload let `UTuple` be `tuple<UTypes...>`.
|
| 1077 |
|
| 1078 |
+
*Constraints:* For all `i`, where 0 ≤ `i` < `sizeof...(TTypes)`,
|
| 1079 |
+
`get<i>(t) == get<i>(u)` is a valid expression and
|
| 1080 |
+
`decltype(get<i>(t) == get<i>(u))` models `boolean-testable`.
|
| 1081 |
+
`sizeof...(TTypes)` equals `tuple_size_v<UTuple>`.
|
|
|
|
|
|
|
| 1082 |
|
| 1083 |
*Returns:* `true` if `get<i>(t) == get<i>(u)` for all `i`, otherwise
|
| 1084 |
`false`.
|
| 1085 |
|
| 1086 |
[*Note 1*: If `sizeof...(TTypes)` equals zero, returns
|
|
|
|
| 1124 |
|
| 1125 |
[*Note 1*: The above definition does not require `tₜₐᵢₗ` (or `uₜₐᵢₗ`)
|
| 1126 |
to be constructed. It might not even be possible, as `t` and `u` are not
|
| 1127 |
required to be copy constructible. Also, all comparison operator
|
| 1128 |
functions are short circuited; they do not perform element accesses
|
| 1129 |
+
beyond what is needed to determine the result of the
|
| 1130 |
comparison. — *end note*]
|
| 1131 |
|
| 1132 |
### `common_reference` related specializations <a id="tuple.common.ref">[[tuple.common.ref]]</a>
|
| 1133 |
|
| 1134 |
In the descriptions that follow:
|
|
|
|
| 1156 |
- `is_same_v<UTuple, decay_t<UTuple>>` is `true`.
|
| 1157 |
- `tuple_size_v<TTuple>` equals `tuple_size_v<UTuple>`.
|
| 1158 |
- `tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>` denotes a
|
| 1159 |
type.
|
| 1160 |
|
| 1161 |
+
*Result:* The member *typedef-name* `type` denotes the type
|
| 1162 |
`tuple<common_reference_t<TQual<TTypes>, UQual<UTypes>>...>`.
|
| 1163 |
|
| 1164 |
``` cpp
|
| 1165 |
template<tuple-like TTuple, tuple-like UTuple>
|
| 1166 |
struct common_type<TTuple, UTuple> {
|
|
|
|
| 1175 |
- `is_same_v<TTuple, decay_t<TTuple>>` is `true`.
|
| 1176 |
- `is_same_v<UTuple, decay_t<UTuple>>` is `true`.
|
| 1177 |
- `tuple_size_v<TTuple>` equals `tuple_size_v<UTuple>`.
|
| 1178 |
- `tuple<common_type_t<TTypes, UTypes>...>` denotes a type.
|
| 1179 |
|
| 1180 |
+
*Result:* The member *typedef-name* `type` denotes the type
|
| 1181 |
`tuple<common_type_t<TTypes, UTypes>...>`.
|
| 1182 |
|
| 1183 |
### Tuple traits <a id="tuple.traits">[[tuple.traits]]</a>
|
| 1184 |
|
| 1185 |
``` cpp
|