- tmp/tmpry53_gj8/{from.md → to.md} +107 -58
tmp/tmpry53_gj8/{from.md → to.md}
RENAMED
|
@@ -17,19 +17,19 @@ namespace std {
|
|
| 17 |
|
| 18 |
// [tuple.creation], tuple creation functions:
|
| 19 |
const unspecified ignore;
|
| 20 |
|
| 21 |
template <class... Types>
|
| 22 |
-
tuple<VTypes...> make_tuple(Types&&...);
|
| 23 |
template <class... Types>
|
| 24 |
-
tuple<Types...> forward_as_tuple(Types&&...) noexcept;
|
| 25 |
|
| 26 |
template<class... Types>
|
| 27 |
-
tuple<Types&...> tie(Types&...) noexcept;
|
| 28 |
|
| 29 |
template <class... Tuples>
|
| 30 |
-
tuple<Ctypes...> tuple_cat(Tuples&&...);
|
| 31 |
|
| 32 |
// [tuple.helper], tuple helper classes:
|
| 33 |
template <class T> class tuple_size; // undefined
|
| 34 |
template <class T> class tuple_size<const T>;
|
| 35 |
template <class T> class tuple_size<volatile T>;
|
|
@@ -42,31 +42,43 @@ namespace std {
|
|
| 42 |
template <size_t I, class T> class tuple_element<I, volatile T>;
|
| 43 |
template <size_t I, class T> class tuple_element<I, const volatile T>;
|
| 44 |
|
| 45 |
template <size_t I, class... Types> class tuple_element<I, tuple<Types...> >;
|
| 46 |
|
|
|
|
|
|
|
|
|
|
| 47 |
// [tuple.elem], element access:
|
| 48 |
template <size_t I, class... Types>
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
// [tuple.rel], relational operators:
|
| 56 |
template<class... TTypes, class... UTypes>
|
| 57 |
-
bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 58 |
template<class... TTypes, class... UTypes>
|
| 59 |
-
bool operator<(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 60 |
template<class... TTypes, class... UTypes>
|
| 61 |
-
bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 62 |
template<class... TTypes, class... UTypes>
|
| 63 |
-
bool operator>(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 64 |
template<class... TTypes, class... UTypes>
|
| 65 |
-
bool operator<=(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 66 |
template<class... TTypes, class... UTypes>
|
| 67 |
-
bool operator>=(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 68 |
|
| 69 |
// [tuple.traits], allocator-related traits
|
| 70 |
template <class... Types, class Alloc>
|
| 71 |
struct uses_allocator<tuple<Types...>, Alloc>;
|
| 72 |
|
|
@@ -84,26 +96,26 @@ namespace std {
|
|
| 84 |
class tuple {
|
| 85 |
public:
|
| 86 |
|
| 87 |
// [tuple.cnstr], tuple construction
|
| 88 |
constexpr tuple();
|
| 89 |
-
explicit tuple(const Types&...);
|
| 90 |
template <class... UTypes>
|
| 91 |
-
explicit tuple(UTypes&&...);
|
| 92 |
|
| 93 |
tuple(const tuple&) = default;
|
| 94 |
tuple(tuple&&) = default;
|
| 95 |
|
| 96 |
template <class... UTypes>
|
| 97 |
-
tuple(const tuple<UTypes...>&);
|
| 98 |
template <class... UTypes>
|
| 99 |
-
tuple(tuple<UTypes...>&&);
|
| 100 |
|
| 101 |
template <class U1, class U2>
|
| 102 |
-
tuple(const pair<U1, U2>&); //
|
| 103 |
template <class U1, class U2>
|
| 104 |
-
tuple(pair<U1, U2>&&); //
|
| 105 |
|
| 106 |
// allocator-extended constructors
|
| 107 |
template <class Alloc>
|
| 108 |
tuple(allocator_arg_t, const Alloc& a);
|
| 109 |
template <class Alloc>
|
|
@@ -131,13 +143,13 @@ namespace std {
|
|
| 131 |
tuple& operator=(const tuple<UTypes...>&);
|
| 132 |
template <class... UTypes>
|
| 133 |
tuple& operator=(tuple<UTypes...>&&);
|
| 134 |
|
| 135 |
template <class U1, class U2>
|
| 136 |
-
tuple& operator=(const pair<U1, U2>&); //
|
| 137 |
template <class U1, class U2>
|
| 138 |
-
tuple& operator=(pair<U1, U2>&&); //
|
| 139 |
|
| 140 |
// [tuple.swap], tuple swap
|
| 141 |
void swap(tuple&) noexcept(see below);
|
| 142 |
};
|
| 143 |
}
|
|
@@ -146,10 +158,16 @@ namespace std {
|
|
| 146 |
#### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
|
| 147 |
|
| 148 |
For each `tuple` constructor, an exception is thrown only if the
|
| 149 |
construction of one of the types in `Types` throws an exception.
|
| 150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
In the constructor descriptions that follow, let i be in the range
|
| 152 |
\[`0`, `sizeof...(Types)`) in order, Tᵢ be the iᵗʰ type in `Types`, and
|
| 153 |
Uᵢ be the iᵗʰ type in a template parameter pack named `UTypes`, where
|
| 154 |
indexing is zero-based.
|
| 155 |
|
|
@@ -160,21 +178,21 @@ constexpr tuple();
|
|
| 160 |
*Requires:* `is_default_constructible<`Tᵢ`>::value` is true for all i.
|
| 161 |
|
| 162 |
*Effects:* Value initializes each element.
|
| 163 |
|
| 164 |
``` cpp
|
| 165 |
-
explicit tuple(const Types&...);
|
| 166 |
```
|
| 167 |
|
| 168 |
*Requires:* `is_copy_constructible<`Tᵢ`>::value` is true for all i.
|
| 169 |
|
| 170 |
*Effects:* Initializes each element with the value of the corresponding
|
| 171 |
parameter.
|
| 172 |
|
| 173 |
``` cpp
|
| 174 |
template <class... UTypes>
|
| 175 |
-
explicit tuple(UTypes&&... u);
|
| 176 |
```
|
| 177 |
|
| 178 |
*Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
|
| 179 |
`is_constructible<`Tᵢ`, `Uᵢ`&&>::value` is `true` for all i.
|
| 180 |
|
|
@@ -202,11 +220,11 @@ tuple(tuple&& u) = default;
|
|
| 202 |
|
| 203 |
*Effects:* For all i, initializes the iᵗʰ element of `*this` with
|
| 204 |
`std::forward<`Tᵢ`>(get<`i`>(u))`.
|
| 205 |
|
| 206 |
``` cpp
|
| 207 |
-
template <class... UTypes> tuple(const tuple<UTypes...>& u);
|
| 208 |
```
|
| 209 |
|
| 210 |
*Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
|
| 211 |
`is_constructible<`Tᵢ`, const `Uᵢ`&>::value` is `true` for all i.
|
| 212 |
|
|
@@ -215,11 +233,11 @@ element of `u`.
|
|
| 215 |
|
| 216 |
This constructor shall not participate in overload resolution unless
|
| 217 |
`const `Uᵢ`&` is implicitly convertible to Tᵢ for all i.
|
| 218 |
|
| 219 |
``` cpp
|
| 220 |
-
template <class... UTypes> tuple(tuple<UTypes...>&& u);
|
| 221 |
```
|
| 222 |
|
| 223 |
*Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
|
| 224 |
`is_constructible<`Tᵢ`, `Uᵢ`&&>::value` is `true` for all i.
|
| 225 |
|
|
@@ -229,11 +247,11 @@ template <class... UTypes> tuple(tuple<UTypes...>&& u);
|
|
| 229 |
This constructor shall not participate in overload resolution unless
|
| 230 |
each type in `UTypes` is implicitly convertible to its corresponding
|
| 231 |
type in `Types`.
|
| 232 |
|
| 233 |
``` cpp
|
| 234 |
-
template <class U1, class U2> tuple(const pair<U1, U2>& u);
|
| 235 |
```
|
| 236 |
|
| 237 |
*Requires:* `sizeof...(Types) == 2`.
|
| 238 |
`is_constructible<`T₀`, const U1&>::value` is `true` for the first type
|
| 239 |
T₀ in `Types` and `is_constructible<`T₁`, const U2&>::value` is `true`
|
|
@@ -245,11 +263,11 @@ element with `u.second`.
|
|
| 245 |
This constructor shall not participate in overload resolution unless
|
| 246 |
`const U1&` is implicitly convertible to T₀ and `const U2&` is
|
| 247 |
implicitly convertible to T₁.
|
| 248 |
|
| 249 |
``` cpp
|
| 250 |
-
template <class U1, class U2> tuple(pair<U1, U2>&& u);
|
| 251 |
```
|
| 252 |
|
| 253 |
*Requires:* `sizeof...(Types) == 2`.
|
| 254 |
`is_constructible<`T₀`, U1&&>::value` is `true` for the first type T₀ in
|
| 255 |
`Types` and `is_constructible<`T₁`, U2&&>::value` is `true` for the
|
|
@@ -398,11 +416,11 @@ The expression inside `noexcept` is equivalent to the logical
|
|
| 398 |
|
| 399 |
``` cpp
|
| 400 |
noexcept(swap(declval<Tᵢ&>>(), declval<Tᵢ&>()))
|
| 401 |
```
|
| 402 |
|
| 403 |
-
where T
|
| 404 |
|
| 405 |
*Requires:* Each element in `*this` shall be swappable
|
| 406 |
with ([[swappable.requirements]]) the corresponding element in `rhs`.
|
| 407 |
|
| 408 |
*Effects:* Calls `swap` for each element in `*this` and its
|
|
@@ -419,14 +437,14 @@ parameter pack named `TTypes`; let j be in the range \[`0`,
|
|
| 419 |
`sizeof...(UTypes)`) in order and Uⱼ be the jᵗʰ type in a template
|
| 420 |
parameter pack named `UTypes`, where indexing is zero-based.
|
| 421 |
|
| 422 |
``` cpp
|
| 423 |
template<class... Types>
|
| 424 |
-
tuple<VTypes...> make_tuple(Types&&... t);
|
| 425 |
```
|
| 426 |
|
| 427 |
-
Let Uᵢ be `
|
| 428 |
`VTypes` is `X&` if Uᵢ equals `reference_wrapper<X>`, otherwise Vᵢ is
|
| 429 |
Uᵢ.
|
| 430 |
|
| 431 |
*Returns:* `tuple<VTypes...>(std::forward<Types>(t)...)`.
|
| 432 |
|
|
@@ -441,11 +459,11 @@ creates a tuple of type
|
|
| 441 |
tuple<int, int&, const float&>
|
| 442 |
```
|
| 443 |
|
| 444 |
``` cpp
|
| 445 |
template<class... Types>
|
| 446 |
-
tuple<Types&&...> forward_as_tuple(Types&&... t) noexcept;
|
| 447 |
```
|
| 448 |
|
| 449 |
*Effects:* Constructs a tuple of references to the arguments in `t`
|
| 450 |
suitable for forwarding as arguments to a function. Because the result
|
| 451 |
may contain references to temporary variables, a program shall ensure
|
|
@@ -455,15 +473,16 @@ named variable).
|
|
| 455 |
|
| 456 |
*Returns:* `tuple<Types&&...>(std::forward<Types>(t)...)`
|
| 457 |
|
| 458 |
``` cpp
|
| 459 |
template<class... Types>
|
| 460 |
-
tuple<Types&...> tie(Types&... t) noexcept;
|
| 461 |
```
|
| 462 |
|
| 463 |
-
*Returns:* `tuple<Types&>(t...)`. When an argument in `t` is
|
| 464 |
-
assigning any value to the corresponding tuple element has no
|
|
|
|
| 465 |
|
| 466 |
`tie` functions allow one to create tuples that unpack tuples into
|
| 467 |
variables. `ignore` can be used for elements that are not needed:
|
| 468 |
|
| 469 |
``` cpp
|
|
@@ -472,16 +491,16 @@ tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
|
|
| 472 |
// i == 42, s == "C++"
|
| 473 |
```
|
| 474 |
|
| 475 |
``` cpp
|
| 476 |
template <class... Tuples>
|
| 477 |
-
tuple<CTypes...> tuple_cat(Tuples&&... tpls);
|
| 478 |
```
|
| 479 |
|
| 480 |
In the following paragraphs, let Tᵢ be the iᵗʰ type in `Tuples`, Uᵢ be
|
| 481 |
-
`
|
| 482 |
-
|
| 483 |
|
| 484 |
*Requires:* For all i, Uᵢ shall be the type cvᵢ `tuple<`Argsᵢ...`>`,
|
| 485 |
where cvᵢ is the (possibly empty) iᵗʰ cv-qualifier-seq and Argsᵢ is the
|
| 486 |
parameter pack representing the element types in Uᵢ. Let {Aᵢₖ} be the
|
| 487 |
kᵢᵗʰ type in Argsᵢ. For all Aᵢₖ the following requirements shall be
|
|
@@ -504,10 +523,18 @@ eᵢ in order.
|
|
| 504 |
pack `Tuples` that support the `tuple`-like protocol, such as `pair` and
|
| 505 |
`array`.
|
| 506 |
|
| 507 |
#### Tuple helper classes <a id="tuple.helper">[[tuple.helper]]</a>
|
| 508 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 509 |
``` cpp
|
| 510 |
template <class... Types>
|
| 511 |
class tuple_size<tuple<Types...> >
|
| 512 |
: public integral_constant<size_t, sizeof...(Types)> { };
|
| 513 |
```
|
|
@@ -535,11 +562,11 @@ template <class T> class tuple_size<const volatile T>;
|
|
| 535 |
Let *TS* denote `tuple_size<T>` of the cv-unqualified type `T`. Then
|
| 536 |
each of the three templates shall meet the `UnaryTypeTrait`
|
| 537 |
requirements ([[meta.rqmts]]) with a `BaseCharacteristic` of
|
| 538 |
|
| 539 |
``` cpp
|
| 540 |
-
integral_constant<
|
| 541 |
```
|
| 542 |
|
| 543 |
``` cpp
|
| 544 |
template <size_t I, class T> class tuple_element<I, const T>;
|
| 545 |
template <size_t I, class T> class tuple_element<I, volatile T>;
|
|
@@ -549,31 +576,30 @@ template <size_t I, class T> class tuple_element<I, const volatile T>;
|
|
| 549 |
Let *TE* denote `tuple_element<I, T>` of the cv-unqualified type `T`.
|
| 550 |
Then each of the three templates shall meet the `TransformationTrait`
|
| 551 |
requirements ([[meta.rqmts]]) with a member typedef `type` that names
|
| 552 |
the following type:
|
| 553 |
|
| 554 |
-
- for the first specialization, `
|
| 555 |
-
- for the second specialization, `
|
| 556 |
-
|
| 557 |
-
- for the third specialization, `add_cv<`*`TE`*`::type>::type`.
|
| 558 |
|
| 559 |
#### Element access <a id="tuple.elem">[[tuple.elem]]</a>
|
| 560 |
|
| 561 |
``` cpp
|
| 562 |
template <size_t I, class... Types>
|
| 563 |
-
|
| 564 |
```
|
| 565 |
|
| 566 |
*Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
|
| 567 |
out of bounds.
|
| 568 |
|
| 569 |
*Returns:* A reference to the `I`th element of `t`, where indexing is
|
| 570 |
zero-based.
|
| 571 |
|
| 572 |
``` cpp
|
| 573 |
-
template <size_t I, class...
|
| 574 |
-
|
| 575 |
```
|
| 576 |
|
| 577 |
*Effects:* Equivalent to
|
| 578 |
`return std::forward<typename tuple_element<I, tuple<Types...> >`
|
| 579 |
`::type&&>(get<I>(t));`
|
|
@@ -582,11 +608,11 @@ template <size_t I, class... types>
|
|
| 582 |
is `X&`, not `X&&`. However, if the element type is a non-reference type
|
| 583 |
`T`, the return type is `T&&`.
|
| 584 |
|
| 585 |
``` cpp
|
| 586 |
template <size_t I, class... Types>
|
| 587 |
-
|
| 588 |
```
|
| 589 |
|
| 590 |
*Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
|
| 591 |
out of bounds.
|
| 592 |
|
|
@@ -597,38 +623,61 @@ Constness is shallow. If a `T` in `Types` is some reference type `X&`,
|
|
| 597 |
the return type is `X&`, not `const X&`. However, if the element type is
|
| 598 |
non-reference type `T`, the return type is `const T&`. This is
|
| 599 |
consistent with how constness is defined to work for member variables of
|
| 600 |
reference type.
|
| 601 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
The reason `get` is a nonmember function is that if this functionality
|
| 603 |
had been provided as a member function, code where the type depended on
|
| 604 |
a template parameter would have required using the `template` keyword.
|
| 605 |
|
| 606 |
#### Relational operators <a id="tuple.rel">[[tuple.rel]]</a>
|
| 607 |
|
| 608 |
``` cpp
|
| 609 |
template<class... TTypes, class... UTypes>
|
| 610 |
-
bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 611 |
```
|
| 612 |
|
| 613 |
-
*Requires:* For all `i`, where `0 <= i` and `i < sizeof...(
|
| 614 |
`get<i>(t) == get<i>(u)` is a valid expression returning a type that is
|
| 615 |
convertible to `bool`. `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
|
| 616 |
|
| 617 |
-
*Returns:* `true`
|
| 618 |
-
zero-length tuples `e` and `f`, `e == f` returns
|
|
|
|
| 619 |
|
| 620 |
*Effects:* The elementary comparisons are performed in order from the
|
| 621 |
zeroth index upwards. No comparisons or element accesses are performed
|
| 622 |
after the first equality comparison that evaluates to `false`.
|
| 623 |
|
| 624 |
``` cpp
|
| 625 |
template<class... TTypes, class... UTypes>
|
| 626 |
-
bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 627 |
```
|
| 628 |
|
| 629 |
-
*Requires:* For all `i`, where `0 <= i` and `i < sizeof...(
|
| 630 |
`get<i>(t) < get<i>(u)` and `get<i>(u) < get<i>(t)` are valid
|
| 631 |
expressions returning types that are convertible to `bool`.
|
| 632 |
`sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
|
| 633 |
|
| 634 |
*Returns:* The result of a lexicographical comparison between `t` and
|
|
@@ -638,32 +687,32 @@ where `r`ₜₐᵢₗ for some tuple `r` is a tuple containing all but the first
|
|
| 638 |
element of `r`. For any two zero-length tuples `e` and `f`, `e < f`
|
| 639 |
returns `false`.
|
| 640 |
|
| 641 |
``` cpp
|
| 642 |
template<class... TTypes, class... UTypes>
|
| 643 |
-
bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 644 |
```
|
| 645 |
|
| 646 |
*Returns:* `!(t == u)`.
|
| 647 |
|
| 648 |
``` cpp
|
| 649 |
template<class... TTypes, class... UTypes>
|
| 650 |
-
bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 651 |
```
|
| 652 |
|
| 653 |
*Returns:* `u < t`.
|
| 654 |
|
| 655 |
``` cpp
|
| 656 |
template<class... TTypes, class... UTypes>
|
| 657 |
-
bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 658 |
```
|
| 659 |
|
| 660 |
*Returns:* `!(u < t)`
|
| 661 |
|
| 662 |
``` cpp
|
| 663 |
template<class... TTypes, class... UTypes>
|
| 664 |
-
bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 665 |
```
|
| 666 |
|
| 667 |
*Returns:* `!(t < u)`
|
| 668 |
|
| 669 |
The above definitions for comparison operators do not require `tₜₐᵢₗ`
|
|
|
|
| 17 |
|
| 18 |
// [tuple.creation], tuple creation functions:
|
| 19 |
const unspecified ignore;
|
| 20 |
|
| 21 |
template <class... Types>
|
| 22 |
+
constexpr tuple<VTypes...> make_tuple(Types&&...);
|
| 23 |
template <class... Types>
|
| 24 |
+
constexpr tuple<Types&&...> forward_as_tuple(Types&&...) noexcept;
|
| 25 |
|
| 26 |
template<class... Types>
|
| 27 |
+
constexpr tuple<Types&...> tie(Types&...) noexcept;
|
| 28 |
|
| 29 |
template <class... Tuples>
|
| 30 |
+
constexpr tuple<Ctypes...> tuple_cat(Tuples&&...);
|
| 31 |
|
| 32 |
// [tuple.helper], tuple helper classes:
|
| 33 |
template <class T> class tuple_size; // undefined
|
| 34 |
template <class T> class tuple_size<const T>;
|
| 35 |
template <class T> class tuple_size<volatile T>;
|
|
|
|
| 42 |
template <size_t I, class T> class tuple_element<I, volatile T>;
|
| 43 |
template <size_t I, class T> class tuple_element<I, const volatile T>;
|
| 44 |
|
| 45 |
template <size_t I, class... Types> class tuple_element<I, tuple<Types...> >;
|
| 46 |
|
| 47 |
+
template <size_t I, class T>
|
| 48 |
+
using tuple_element_t = typename tuple_element<I, T>::type;
|
| 49 |
+
|
| 50 |
// [tuple.elem], element access:
|
| 51 |
template <size_t I, class... Types>
|
| 52 |
+
constexpr tuple_element_t<I, tuple<Types...>>&
|
| 53 |
+
get(tuple<Types...>&) noexcept;
|
| 54 |
+
template <size_t I, class... Types>
|
| 55 |
+
constexpr tuple_element_t<I, tuple<Types...>>&&
|
| 56 |
+
get(tuple<Types...>&&) noexcept;
|
| 57 |
+
template <size_t I, class... Types>
|
| 58 |
+
constexpr const tuple_element_t<I, tuple<Types...>>&
|
| 59 |
+
get(const tuple<Types...>&) noexcept;
|
| 60 |
+
template <class T, class... Types>
|
| 61 |
+
constexpr T& get(tuple<Types...>& t) noexcept;
|
| 62 |
+
template <class T, class... Types>
|
| 63 |
+
constexpr T&& get(tuple<Types...>&& t) noexcept;
|
| 64 |
+
template <class T, class... Types>
|
| 65 |
+
constexpr const T& get(const tuple<Types...>& t) noexcept;
|
| 66 |
|
| 67 |
// [tuple.rel], relational operators:
|
| 68 |
template<class... TTypes, class... UTypes>
|
| 69 |
+
constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 70 |
template<class... TTypes, class... UTypes>
|
| 71 |
+
constexpr bool operator<(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 72 |
template<class... TTypes, class... UTypes>
|
| 73 |
+
constexpr bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 74 |
template<class... TTypes, class... UTypes>
|
| 75 |
+
constexpr bool operator>(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 76 |
template<class... TTypes, class... UTypes>
|
| 77 |
+
constexpr bool operator<=(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 78 |
template<class... TTypes, class... UTypes>
|
| 79 |
+
constexpr bool operator>=(const tuple<TTypes...>&, const tuple<UTypes...>&);
|
| 80 |
|
| 81 |
// [tuple.traits], allocator-related traits
|
| 82 |
template <class... Types, class Alloc>
|
| 83 |
struct uses_allocator<tuple<Types...>, Alloc>;
|
| 84 |
|
|
|
|
| 96 |
class tuple {
|
| 97 |
public:
|
| 98 |
|
| 99 |
// [tuple.cnstr], tuple construction
|
| 100 |
constexpr tuple();
|
| 101 |
+
constexpr explicit tuple(const Types&...);
|
| 102 |
template <class... UTypes>
|
| 103 |
+
constexpr explicit tuple(UTypes&&...);
|
| 104 |
|
| 105 |
tuple(const tuple&) = default;
|
| 106 |
tuple(tuple&&) = default;
|
| 107 |
|
| 108 |
template <class... UTypes>
|
| 109 |
+
constexpr tuple(const tuple<UTypes...>&);
|
| 110 |
template <class... UTypes>
|
| 111 |
+
constexpr tuple(tuple<UTypes...>&&);
|
| 112 |
|
| 113 |
template <class U1, class U2>
|
| 114 |
+
constexpr tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2
|
| 115 |
template <class U1, class U2>
|
| 116 |
+
constexpr tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2
|
| 117 |
|
| 118 |
// allocator-extended constructors
|
| 119 |
template <class Alloc>
|
| 120 |
tuple(allocator_arg_t, const Alloc& a);
|
| 121 |
template <class Alloc>
|
|
|
|
| 143 |
tuple& operator=(const tuple<UTypes...>&);
|
| 144 |
template <class... UTypes>
|
| 145 |
tuple& operator=(tuple<UTypes...>&&);
|
| 146 |
|
| 147 |
template <class U1, class U2>
|
| 148 |
+
tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2
|
| 149 |
template <class U1, class U2>
|
| 150 |
+
tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2
|
| 151 |
|
| 152 |
// [tuple.swap], tuple swap
|
| 153 |
void swap(tuple&) noexcept(see below);
|
| 154 |
};
|
| 155 |
}
|
|
|
|
| 158 |
#### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
|
| 159 |
|
| 160 |
For each `tuple` constructor, an exception is thrown only if the
|
| 161 |
construction of one of the types in `Types` throws an exception.
|
| 162 |
|
| 163 |
+
The defaulted move and copy constructor, respectively, of `tuple` shall
|
| 164 |
+
be a `constexpr` function if and only if all required element-wise
|
| 165 |
+
initializations for copy and move, respectively, would satisfy the
|
| 166 |
+
requirements for a `constexpr` function. The defaulted move and copy
|
| 167 |
+
constructor of `tuple<>` shall be `constexpr` functions.
|
| 168 |
+
|
| 169 |
In the constructor descriptions that follow, let i be in the range
|
| 170 |
\[`0`, `sizeof...(Types)`) in order, Tᵢ be the iᵗʰ type in `Types`, and
|
| 171 |
Uᵢ be the iᵗʰ type in a template parameter pack named `UTypes`, where
|
| 172 |
indexing is zero-based.
|
| 173 |
|
|
|
|
| 178 |
*Requires:* `is_default_constructible<`Tᵢ`>::value` is true for all i.
|
| 179 |
|
| 180 |
*Effects:* Value initializes each element.
|
| 181 |
|
| 182 |
``` cpp
|
| 183 |
+
constexpr explicit tuple(const Types&...);
|
| 184 |
```
|
| 185 |
|
| 186 |
*Requires:* `is_copy_constructible<`Tᵢ`>::value` is true for all i.
|
| 187 |
|
| 188 |
*Effects:* Initializes each element with the value of the corresponding
|
| 189 |
parameter.
|
| 190 |
|
| 191 |
``` cpp
|
| 192 |
template <class... UTypes>
|
| 193 |
+
constexpr explicit tuple(UTypes&&... u);
|
| 194 |
```
|
| 195 |
|
| 196 |
*Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
|
| 197 |
`is_constructible<`Tᵢ`, `Uᵢ`&&>::value` is `true` for all i.
|
| 198 |
|
|
|
|
| 220 |
|
| 221 |
*Effects:* For all i, initializes the iᵗʰ element of `*this` with
|
| 222 |
`std::forward<`Tᵢ`>(get<`i`>(u))`.
|
| 223 |
|
| 224 |
``` cpp
|
| 225 |
+
template <class... UTypes> constexpr tuple(const tuple<UTypes...>& u);
|
| 226 |
```
|
| 227 |
|
| 228 |
*Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
|
| 229 |
`is_constructible<`Tᵢ`, const `Uᵢ`&>::value` is `true` for all i.
|
| 230 |
|
|
|
|
| 233 |
|
| 234 |
This constructor shall not participate in overload resolution unless
|
| 235 |
`const `Uᵢ`&` is implicitly convertible to Tᵢ for all i.
|
| 236 |
|
| 237 |
``` cpp
|
| 238 |
+
template <class... UTypes> constexpr tuple(tuple<UTypes...>&& u);
|
| 239 |
```
|
| 240 |
|
| 241 |
*Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
|
| 242 |
`is_constructible<`Tᵢ`, `Uᵢ`&&>::value` is `true` for all i.
|
| 243 |
|
|
|
|
| 247 |
This constructor shall not participate in overload resolution unless
|
| 248 |
each type in `UTypes` is implicitly convertible to its corresponding
|
| 249 |
type in `Types`.
|
| 250 |
|
| 251 |
``` cpp
|
| 252 |
+
template <class U1, class U2> constexpr tuple(const pair<U1, U2>& u);
|
| 253 |
```
|
| 254 |
|
| 255 |
*Requires:* `sizeof...(Types) == 2`.
|
| 256 |
`is_constructible<`T₀`, const U1&>::value` is `true` for the first type
|
| 257 |
T₀ in `Types` and `is_constructible<`T₁`, const U2&>::value` is `true`
|
|
|
|
| 263 |
This constructor shall not participate in overload resolution unless
|
| 264 |
`const U1&` is implicitly convertible to T₀ and `const U2&` is
|
| 265 |
implicitly convertible to T₁.
|
| 266 |
|
| 267 |
``` cpp
|
| 268 |
+
template <class U1, class U2> constexpr tuple(pair<U1, U2>&& u);
|
| 269 |
```
|
| 270 |
|
| 271 |
*Requires:* `sizeof...(Types) == 2`.
|
| 272 |
`is_constructible<`T₀`, U1&&>::value` is `true` for the first type T₀ in
|
| 273 |
`Types` and `is_constructible<`T₁`, U2&&>::value` is `true` for the
|
|
|
|
| 416 |
|
| 417 |
``` cpp
|
| 418 |
noexcept(swap(declval<Tᵢ&>>(), declval<Tᵢ&>()))
|
| 419 |
```
|
| 420 |
|
| 421 |
+
where Tᵢ is the iᵗʰ type in `Types`.
|
| 422 |
|
| 423 |
*Requires:* Each element in `*this` shall be swappable
|
| 424 |
with ([[swappable.requirements]]) the corresponding element in `rhs`.
|
| 425 |
|
| 426 |
*Effects:* Calls `swap` for each element in `*this` and its
|
|
|
|
| 437 |
`sizeof...(UTypes)`) in order and Uⱼ be the jᵗʰ type in a template
|
| 438 |
parameter pack named `UTypes`, where indexing is zero-based.
|
| 439 |
|
| 440 |
``` cpp
|
| 441 |
template<class... Types>
|
| 442 |
+
constexpr tuple<VTypes...> make_tuple(Types&&... t);
|
| 443 |
```
|
| 444 |
|
| 445 |
+
Let Uᵢ be `decay_t<`Tᵢ`>` for each Tᵢ in `Types`. Then each Vᵢ in
|
| 446 |
`VTypes` is `X&` if Uᵢ equals `reference_wrapper<X>`, otherwise Vᵢ is
|
| 447 |
Uᵢ.
|
| 448 |
|
| 449 |
*Returns:* `tuple<VTypes...>(std::forward<Types>(t)...)`.
|
| 450 |
|
|
|
|
| 459 |
tuple<int, int&, const float&>
|
| 460 |
```
|
| 461 |
|
| 462 |
``` cpp
|
| 463 |
template<class... Types>
|
| 464 |
+
constexpr tuple<Types&&...> forward_as_tuple(Types&&... t) noexcept;
|
| 465 |
```
|
| 466 |
|
| 467 |
*Effects:* Constructs a tuple of references to the arguments in `t`
|
| 468 |
suitable for forwarding as arguments to a function. Because the result
|
| 469 |
may contain references to temporary variables, a program shall ensure
|
|
|
|
| 473 |
|
| 474 |
*Returns:* `tuple<Types&&...>(std::forward<Types>(t)...)`
|
| 475 |
|
| 476 |
``` cpp
|
| 477 |
template<class... Types>
|
| 478 |
+
constexpr tuple<Types&...> tie(Types&... t) noexcept;
|
| 479 |
```
|
| 480 |
|
| 481 |
+
*Returns:* `tuple<Types&...>(t...)`. When an argument in `t` is
|
| 482 |
+
`ignore`, assigning any value to the corresponding tuple element has no
|
| 483 |
+
effect.
|
| 484 |
|
| 485 |
`tie` functions allow one to create tuples that unpack tuples into
|
| 486 |
variables. `ignore` can be used for elements that are not needed:
|
| 487 |
|
| 488 |
``` cpp
|
|
|
|
| 491 |
// i == 42, s == "C++"
|
| 492 |
```
|
| 493 |
|
| 494 |
``` cpp
|
| 495 |
template <class... Tuples>
|
| 496 |
+
constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
|
| 497 |
```
|
| 498 |
|
| 499 |
In the following paragraphs, let Tᵢ be the iᵗʰ type in `Tuples`, Uᵢ be
|
| 500 |
+
`remove_reference_t<Ti>`, and tpᵢ be the iᵗʰ parameter in the function
|
| 501 |
+
parameter pack `tpls`, where all indexing is zero-based.
|
| 502 |
|
| 503 |
*Requires:* For all i, Uᵢ shall be the type cvᵢ `tuple<`Argsᵢ...`>`,
|
| 504 |
where cvᵢ is the (possibly empty) iᵗʰ cv-qualifier-seq and Argsᵢ is the
|
| 505 |
parameter pack representing the element types in Uᵢ. Let {Aᵢₖ} be the
|
| 506 |
kᵢᵗʰ type in Argsᵢ. For all Aᵢₖ the following requirements shall be
|
|
|
|
| 523 |
pack `Tuples` that support the `tuple`-like protocol, such as `pair` and
|
| 524 |
`array`.
|
| 525 |
|
| 526 |
#### Tuple helper classes <a id="tuple.helper">[[tuple.helper]]</a>
|
| 527 |
|
| 528 |
+
``` cpp
|
| 529 |
+
template <class T> struct tuple_size;
|
| 530 |
+
```
|
| 531 |
+
|
| 532 |
+
*Remarks:* All specializations of `tuple_size<T>` shall meet the
|
| 533 |
+
`UnaryTypeTrait` requirements ([[meta.rqmts]]) with a
|
| 534 |
+
`BaseCharacteristic` of `integral_constant<size_t, N>` for some `N`.
|
| 535 |
+
|
| 536 |
``` cpp
|
| 537 |
template <class... Types>
|
| 538 |
class tuple_size<tuple<Types...> >
|
| 539 |
: public integral_constant<size_t, sizeof...(Types)> { };
|
| 540 |
```
|
|
|
|
| 562 |
Let *TS* denote `tuple_size<T>` of the cv-unqualified type `T`. Then
|
| 563 |
each of the three templates shall meet the `UnaryTypeTrait`
|
| 564 |
requirements ([[meta.rqmts]]) with a `BaseCharacteristic` of
|
| 565 |
|
| 566 |
``` cpp
|
| 567 |
+
integral_constant<size_t, TS::value>
|
| 568 |
```
|
| 569 |
|
| 570 |
``` cpp
|
| 571 |
template <size_t I, class T> class tuple_element<I, const T>;
|
| 572 |
template <size_t I, class T> class tuple_element<I, volatile T>;
|
|
|
|
| 576 |
Let *TE* denote `tuple_element<I, T>` of the cv-unqualified type `T`.
|
| 577 |
Then each of the three templates shall meet the `TransformationTrait`
|
| 578 |
requirements ([[meta.rqmts]]) with a member typedef `type` that names
|
| 579 |
the following type:
|
| 580 |
|
| 581 |
+
- for the first specialization, `add_const_t<`*`TE`*`::type>`,
|
| 582 |
+
- for the second specialization, `add_volatile_t<`*`TE`*`::type>`, and
|
| 583 |
+
- for the third specialization, `add_cv_t<`*`TE`*`::type>`.
|
|
|
|
| 584 |
|
| 585 |
#### Element access <a id="tuple.elem">[[tuple.elem]]</a>
|
| 586 |
|
| 587 |
``` cpp
|
| 588 |
template <size_t I, class... Types>
|
| 589 |
+
constexpr tuple_element_t<I, tuple<Types...> >& get(tuple<Types...>& t) noexcept;
|
| 590 |
```
|
| 591 |
|
| 592 |
*Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
|
| 593 |
out of bounds.
|
| 594 |
|
| 595 |
*Returns:* A reference to the `I`th element of `t`, where indexing is
|
| 596 |
zero-based.
|
| 597 |
|
| 598 |
``` cpp
|
| 599 |
+
template <size_t I, class... Types>
|
| 600 |
+
constexpr tuple_element_t<I, tuple<Types...> >&& get(tuple<Types...>&& t) noexcept;
|
| 601 |
```
|
| 602 |
|
| 603 |
*Effects:* Equivalent to
|
| 604 |
`return std::forward<typename tuple_element<I, tuple<Types...> >`
|
| 605 |
`::type&&>(get<I>(t));`
|
|
|
|
| 608 |
is `X&`, not `X&&`. However, if the element type is a non-reference type
|
| 609 |
`T`, the return type is `T&&`.
|
| 610 |
|
| 611 |
``` cpp
|
| 612 |
template <size_t I, class... Types>
|
| 613 |
+
constexpr tuple_element_t<I, tuple<Types...> > const& get(const tuple<Types...>& t) noexcept;
|
| 614 |
```
|
| 615 |
|
| 616 |
*Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
|
| 617 |
out of bounds.
|
| 618 |
|
|
|
|
| 623 |
the return type is `X&`, not `const X&`. However, if the element type is
|
| 624 |
non-reference type `T`, the return type is `const T&`. This is
|
| 625 |
consistent with how constness is defined to work for member variables of
|
| 626 |
reference type.
|
| 627 |
|
| 628 |
+
``` cpp
|
| 629 |
+
template <class T, class... Types>
|
| 630 |
+
constexpr T& get(tuple<Types...>& t) noexcept;
|
| 631 |
+
template <class T, class... Types>
|
| 632 |
+
constexpr T&& get(tuple<Types...>&& t) noexcept;
|
| 633 |
+
template <class T, class... Types>
|
| 634 |
+
constexpr const T& get(const tuple<Types...>& t) noexcept;
|
| 635 |
+
```
|
| 636 |
+
|
| 637 |
+
*Requires:* The type `T` occurs exactly once in `Types...`. Otherwise,
|
| 638 |
+
the program is ill-formed.
|
| 639 |
+
|
| 640 |
+
*Returns:* A reference to the element of `t` corresponding to the type
|
| 641 |
+
`T` in `Types...`.
|
| 642 |
+
|
| 643 |
+
``` cpp
|
| 644 |
+
const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
|
| 645 |
+
const int &i1 = get<int>(t); // OK. Not ambiguous. i1 == 1
|
| 646 |
+
const int &i2 = get<const int>(t); // OK. Not ambiguous. i2 == 2
|
| 647 |
+
const double &d = get<double>(t); // ERROR. ill-formed
|
| 648 |
+
```
|
| 649 |
+
|
| 650 |
The reason `get` is a nonmember function is that if this functionality
|
| 651 |
had been provided as a member function, code where the type depended on
|
| 652 |
a template parameter would have required using the `template` keyword.
|
| 653 |
|
| 654 |
#### Relational operators <a id="tuple.rel">[[tuple.rel]]</a>
|
| 655 |
|
| 656 |
``` cpp
|
| 657 |
template<class... TTypes, class... UTypes>
|
| 658 |
+
constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 659 |
```
|
| 660 |
|
| 661 |
+
*Requires:* For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`,
|
| 662 |
`get<i>(t) == get<i>(u)` is a valid expression returning a type that is
|
| 663 |
convertible to `bool`. `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
|
| 664 |
|
| 665 |
+
*Returns:* `true` if `get<i>(t) == get<i>(u)` for all `i`, otherwise
|
| 666 |
+
`false`. For any two zero-length tuples `e` and `f`, `e == f` returns
|
| 667 |
+
`true`.
|
| 668 |
|
| 669 |
*Effects:* The elementary comparisons are performed in order from the
|
| 670 |
zeroth index upwards. No comparisons or element accesses are performed
|
| 671 |
after the first equality comparison that evaluates to `false`.
|
| 672 |
|
| 673 |
``` cpp
|
| 674 |
template<class... TTypes, class... UTypes>
|
| 675 |
+
constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 676 |
```
|
| 677 |
|
| 678 |
+
*Requires:* For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`,
|
| 679 |
`get<i>(t) < get<i>(u)` and `get<i>(u) < get<i>(t)` are valid
|
| 680 |
expressions returning types that are convertible to `bool`.
|
| 681 |
`sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
|
| 682 |
|
| 683 |
*Returns:* The result of a lexicographical comparison between `t` and
|
|
|
|
| 687 |
element of `r`. For any two zero-length tuples `e` and `f`, `e < f`
|
| 688 |
returns `false`.
|
| 689 |
|
| 690 |
``` cpp
|
| 691 |
template<class... TTypes, class... UTypes>
|
| 692 |
+
constexpr bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 693 |
```
|
| 694 |
|
| 695 |
*Returns:* `!(t == u)`.
|
| 696 |
|
| 697 |
``` cpp
|
| 698 |
template<class... TTypes, class... UTypes>
|
| 699 |
+
constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 700 |
```
|
| 701 |
|
| 702 |
*Returns:* `u < t`.
|
| 703 |
|
| 704 |
``` cpp
|
| 705 |
template<class... TTypes, class... UTypes>
|
| 706 |
+
constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 707 |
```
|
| 708 |
|
| 709 |
*Returns:* `!(u < t)`
|
| 710 |
|
| 711 |
``` cpp
|
| 712 |
template<class... TTypes, class... UTypes>
|
| 713 |
+
constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
|
| 714 |
```
|
| 715 |
|
| 716 |
*Returns:* `!(t < u)`
|
| 717 |
|
| 718 |
The above definitions for comparison operators do not require `tₜₐᵢₗ`
|