From Jason Turner

[tuple.tuple]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpzrfgc1_7/{from.md → to.md} +80 -43
tmp/tmpzrfgc1_7/{from.md → to.md} RENAMED
@@ -6,26 +6,26 @@ namespace std {
6
  class tuple {
7
  public:
8
 
9
  // [tuple.cnstr], tuple construction
10
  constexpr tuple();
11
- explicit tuple(const Types&...);
12
  template <class... UTypes>
13
- explicit tuple(UTypes&&...);
14
 
15
  tuple(const tuple&) = default;
16
  tuple(tuple&&) = default;
17
 
18
  template <class... UTypes>
19
- tuple(const tuple<UTypes...>&);
20
  template <class... UTypes>
21
- tuple(tuple<UTypes...>&&);
22
 
23
  template <class U1, class U2>
24
- tuple(const pair<U1, U2>&); // iff sizeof...(Types) == 2
25
  template <class U1, class U2>
26
- tuple(pair<U1, U2>&&); // iff sizeof...(Types) == 2
27
 
28
  // allocator-extended constructors
29
  template <class Alloc>
30
  tuple(allocator_arg_t, const Alloc& a);
31
  template <class Alloc>
@@ -53,13 +53,13 @@ namespace std {
53
  tuple& operator=(const tuple<UTypes...>&);
54
  template <class... UTypes>
55
  tuple& operator=(tuple<UTypes...>&&);
56
 
57
  template <class U1, class U2>
58
- tuple& operator=(const pair<U1, U2>&); // iff sizeof...(Types) == 2
59
  template <class U1, class U2>
60
- tuple& operator=(pair<U1, U2>&&); // iff sizeof...(Types) == 2
61
 
62
  // [tuple.swap], tuple swap
63
  void swap(tuple&) noexcept(see below);
64
  };
65
  }
@@ -68,10 +68,16 @@ namespace std {
68
  #### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
69
 
70
  For each `tuple` constructor, an exception is thrown only if the
71
  construction of one of the types in `Types` throws an exception.
72
 
 
 
 
 
 
 
73
  In the constructor descriptions that follow, let i be in the range
74
  \[`0`, `sizeof...(Types)`) in order, Tᵢ be the iᵗʰ type in `Types`, and
75
  Uᵢ be the iᵗʰ type in a template parameter pack named `UTypes`, where
76
  indexing is zero-based.
77
 
@@ -82,21 +88,21 @@ constexpr tuple();
82
  *Requires:* `is_default_constructible<`Tᵢ`>::value` is true for all i.
83
 
84
  *Effects:* Value initializes each element.
85
 
86
  ``` cpp
87
- explicit tuple(const Types&...);
88
  ```
89
 
90
  *Requires:* `is_copy_constructible<`Tᵢ`>::value` is true for all i.
91
 
92
  *Effects:* Initializes each element with the value of the corresponding
93
  parameter.
94
 
95
  ``` cpp
96
  template <class... UTypes>
97
- explicit tuple(UTypes&&... u);
98
  ```
99
 
100
  *Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
101
  `is_constructible<`Tᵢ`, `Uᵢ`&&>::value` is `true` for all i.
102
 
@@ -124,11 +130,11 @@ tuple(tuple&& u) = default;
124
 
125
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
126
  `std::forward<`Tᵢ`>(get<`i`>(u))`.
127
 
128
  ``` cpp
129
- template <class... UTypes> tuple(const tuple<UTypes...>& u);
130
  ```
131
 
132
  *Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
133
  `is_constructible<`Tᵢ`, const `Uᵢ`&>::value` is `true` for all i.
134
 
@@ -137,11 +143,11 @@ element of `u`.
137
 
138
  This constructor shall not participate in overload resolution unless
139
  `const `Uᵢ`&` is implicitly convertible to Tᵢ for all i.
140
 
141
  ``` cpp
142
- template <class... UTypes> tuple(tuple<UTypes...>&& u);
143
  ```
144
 
145
  *Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
146
  `is_constructible<`Tᵢ`, `Uᵢ`&&>::value` is `true` for all i.
147
 
@@ -151,11 +157,11 @@ template <class... UTypes> tuple(tuple<UTypes...>&& u);
151
  This constructor shall not participate in overload resolution unless
152
  each type in `UTypes` is implicitly convertible to its corresponding
153
  type in `Types`.
154
 
155
  ``` cpp
156
- template <class U1, class U2> tuple(const pair<U1, U2>& u);
157
  ```
158
 
159
  *Requires:* `sizeof...(Types) == 2`.
160
  `is_constructible<`T₀`, const U1&>::value` is `true` for the first type
161
  T₀ in `Types` and `is_constructible<`T₁`, const U2&>::value` is `true`
@@ -167,11 +173,11 @@ element with `u.second`.
167
  This constructor shall not participate in overload resolution unless
168
  `const U1&` is implicitly convertible to T₀ and `const U2&` is
169
  implicitly convertible to T₁.
170
 
171
  ``` cpp
172
- template <class U1, class U2> tuple(pair<U1, U2>&& u);
173
  ```
174
 
175
  *Requires:* `sizeof...(Types) == 2`.
176
  `is_constructible<`T₀`, U1&&>::value` is `true` for the first type T₀ in
177
  `Types` and `is_constructible<`T₁`, U2&&>::value` is `true` for the
@@ -320,11 +326,11 @@ The expression inside `noexcept` is equivalent to the logical
320
 
321
  ``` cpp
322
  noexcept(swap(declval<Tᵢ&>>(), declval<Tᵢ&>()))
323
  ```
324
 
325
- where T is the iᵗʰ type in `Types`.
326
 
327
  *Requires:* Each element in `*this` shall be swappable
328
  with ([[swappable.requirements]]) the corresponding element in `rhs`.
329
 
330
  *Effects:* Calls `swap` for each element in `*this` and its
@@ -341,14 +347,14 @@ parameter pack named `TTypes`; let j be in the range \[`0`,
341
  `sizeof...(UTypes)`) in order and Uⱼ be the jᵗʰ type in a template
342
  parameter pack named `UTypes`, where indexing is zero-based.
343
 
344
  ``` cpp
345
  template<class... Types>
346
- tuple<VTypes...> make_tuple(Types&&... t);
347
  ```
348
 
349
- Let Uᵢ be `decay<`Tᵢ`>::type` for each Tᵢ in `Types`. Then each Vᵢ in
350
  `VTypes` is `X&` if Uᵢ equals `reference_wrapper<X>`, otherwise Vᵢ is
351
  Uᵢ.
352
 
353
  *Returns:* `tuple<VTypes...>(std::forward<Types>(t)...)`.
354
 
@@ -363,11 +369,11 @@ creates a tuple of type
363
  tuple<int, int&, const float&>
364
  ```
365
 
366
  ``` cpp
367
  template<class... Types>
368
- tuple<Types&&...> forward_as_tuple(Types&&... t) noexcept;
369
  ```
370
 
371
  *Effects:* Constructs a tuple of references to the arguments in `t`
372
  suitable for forwarding as arguments to a function. Because the result
373
  may contain references to temporary variables, a program shall ensure
@@ -377,15 +383,16 @@ named variable).
377
 
378
  *Returns:* `tuple<Types&&...>(std::forward<Types>(t)...)`
379
 
380
  ``` cpp
381
  template<class... Types>
382
- tuple<Types&...> tie(Types&... t) noexcept;
383
  ```
384
 
385
- *Returns:* `tuple<Types&>(t...)`. When an argument in `t` is `ignore`,
386
- assigning any value to the corresponding tuple element has no effect.
 
387
 
388
  `tie` functions allow one to create tuples that unpack tuples into
389
  variables. `ignore` can be used for elements that are not needed:
390
 
391
  ``` cpp
@@ -394,16 +401,16 @@ tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
394
  // i == 42, s == "C++"
395
  ```
396
 
397
  ``` cpp
398
  template <class... Tuples>
399
- tuple<CTypes...> tuple_cat(Tuples&&... tpls);
400
  ```
401
 
402
  In the following paragraphs, let Tᵢ be the iᵗʰ type in `Tuples`, Uᵢ be
403
- `remove_reference<Ti>::type`, and tpᵢ be the iᵗʰ parameter in the
404
- function parameter pack `tpls`, where all indexing is zero-based.
405
 
406
  *Requires:* For all i, Uᵢ shall be the type cvᵢ `tuple<`Argsᵢ...`>`,
407
  where cvᵢ is the (possibly empty) iᵗʰ cv-qualifier-seq and Argsᵢ is the
408
  parameter pack representing the element types in Uᵢ. Let {Aᵢₖ} be the
409
  kᵢᵗʰ type in Argsᵢ. For all Aᵢₖ the following requirements shall be
@@ -426,10 +433,18 @@ eᵢ in order.
426
  pack `Tuples` that support the `tuple`-like protocol, such as `pair` and
427
  `array`.
428
 
429
  #### Tuple helper classes <a id="tuple.helper">[[tuple.helper]]</a>
430
 
 
 
 
 
 
 
 
 
431
  ``` cpp
432
  template <class... Types>
433
  class tuple_size<tuple<Types...> >
434
  : public integral_constant<size_t, sizeof...(Types)> { };
435
  ```
@@ -457,11 +472,11 @@ template <class T> class tuple_size<const volatile T>;
457
  Let *TS* denote `tuple_size<T>` of the cv-unqualified type `T`. Then
458
  each of the three templates shall meet the `UnaryTypeTrait`
459
  requirements ([[meta.rqmts]]) with a `BaseCharacteristic` of
460
 
461
  ``` cpp
462
- integral_constant<remove_cv<decltype(TS::value)>::type, TS::value>
463
  ```
464
 
465
  ``` cpp
466
  template <size_t I, class T> class tuple_element<I, const T>;
467
  template <size_t I, class T> class tuple_element<I, volatile T>;
@@ -471,31 +486,30 @@ template <size_t I, class T> class tuple_element<I, const volatile T>;
471
  Let *TE* denote `tuple_element<I, T>` of the cv-unqualified type `T`.
472
  Then each of the three templates shall meet the `TransformationTrait`
473
  requirements ([[meta.rqmts]]) with a member typedef `type` that names
474
  the following type:
475
 
476
- - for the first specialization, `add_const<`*`TE`*`::type>::type`,
477
- - for the second specialization, `add_volatile<`*`TE`*`::type>::type`,
478
- and
479
- - for the third specialization, `add_cv<`*`TE`*`::type>::type`.
480
 
481
  #### Element access <a id="tuple.elem">[[tuple.elem]]</a>
482
 
483
  ``` cpp
484
  template <size_t I, class... Types>
485
- typename tuple_element<I, tuple<Types...> >::type& get(tuple<Types...>& t) noexcept;
486
  ```
487
 
488
  *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
489
  out of bounds.
490
 
491
  *Returns:* A reference to the `I`th element of `t`, where indexing is
492
  zero-based.
493
 
494
  ``` cpp
495
- template <size_t I, class... types>
496
- typename tuple_element<I, tuple<Types...> >::type&& get(tuple<Types...>&& t) noexcept;
497
  ```
498
 
499
  *Effects:* Equivalent to
500
  `return std::forward<typename tuple_element<I, tuple<Types...> >`
501
  `::type&&>(get<I>(t));`
@@ -504,11 +518,11 @@ template <size_t I, class... types>
504
  is `X&`, not `X&&`. However, if the element type is a non-reference type
505
  `T`, the return type is `T&&`.
506
 
507
  ``` cpp
508
  template <size_t I, class... Types>
509
- typename tuple_element<I, tuple<Types...> >::type const& get(const tuple<Types...>& t) noexcept;
510
  ```
511
 
512
  *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
513
  out of bounds.
514
 
@@ -519,38 +533,61 @@ Constness is shallow. If a `T` in `Types` is some reference type `X&`,
519
  the return type is `X&`, not `const X&`. However, if the element type is
520
  non-reference type `T`, the return type is `const T&`. This is
521
  consistent with how constness is defined to work for member variables of
522
  reference type.
523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  The reason `get` is a nonmember function is that if this functionality
525
  had been provided as a member function, code where the type depended on
526
  a template parameter would have required using the `template` keyword.
527
 
528
  #### Relational operators <a id="tuple.rel">[[tuple.rel]]</a>
529
 
530
  ``` cpp
531
  template<class... TTypes, class... UTypes>
532
- bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
533
  ```
534
 
535
- *Requires:* For all `i`, where `0 <= i` and `i < sizeof...(Types)`,
536
  `get<i>(t) == get<i>(u)` is a valid expression returning a type that is
537
  convertible to `bool`. `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
538
 
539
- *Returns:* `true` iff `get<i>(t) == get<i>(u)` for all `i`. For any two
540
- zero-length tuples `e` and `f`, `e == f` returns `true`.
 
541
 
542
  *Effects:* The elementary comparisons are performed in order from the
543
  zeroth index upwards. No comparisons or element accesses are performed
544
  after the first equality comparison that evaluates to `false`.
545
 
546
  ``` cpp
547
  template<class... TTypes, class... UTypes>
548
- bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
549
  ```
550
 
551
- *Requires:* For all `i`, where `0 <= i` and `i < sizeof...(Types)`,
552
  `get<i>(t) < get<i>(u)` and `get<i>(u) < get<i>(t)` are valid
553
  expressions returning types that are convertible to `bool`.
554
  `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
555
 
556
  *Returns:* The result of a lexicographical comparison between `t` and
@@ -560,32 +597,32 @@ where `r`ₜₐᵢₗ for some tuple `r` is a tuple containing all but the first
560
  element of `r`. For any two zero-length tuples `e` and `f`, `e < f`
561
  returns `false`.
562
 
563
  ``` cpp
564
  template<class... TTypes, class... UTypes>
565
- bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
566
  ```
567
 
568
  *Returns:* `!(t == u)`.
569
 
570
  ``` cpp
571
  template<class... TTypes, class... UTypes>
572
- bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
573
  ```
574
 
575
  *Returns:* `u < t`.
576
 
577
  ``` cpp
578
  template<class... TTypes, class... UTypes>
579
- bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
580
  ```
581
 
582
  *Returns:* `!(u < t)`
583
 
584
  ``` cpp
585
  template<class... TTypes, class... UTypes>
586
- bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
587
  ```
588
 
589
  *Returns:* `!(t < u)`
590
 
591
  The above definitions for comparison operators do not require `tₜₐᵢₗ`
 
6
  class tuple {
7
  public:
8
 
9
  // [tuple.cnstr], tuple construction
10
  constexpr tuple();
11
+ constexpr explicit tuple(const Types&...);
12
  template <class... UTypes>
13
+ constexpr explicit tuple(UTypes&&...);
14
 
15
  tuple(const tuple&) = default;
16
  tuple(tuple&&) = default;
17
 
18
  template <class... UTypes>
19
+ constexpr tuple(const tuple<UTypes...>&);
20
  template <class... UTypes>
21
+ constexpr tuple(tuple<UTypes...>&&);
22
 
23
  template <class U1, class U2>
24
+ constexpr tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2
25
  template <class U1, class U2>
26
+ constexpr tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2
27
 
28
  // allocator-extended constructors
29
  template <class Alloc>
30
  tuple(allocator_arg_t, const Alloc& a);
31
  template <class Alloc>
 
53
  tuple& operator=(const tuple<UTypes...>&);
54
  template <class... UTypes>
55
  tuple& operator=(tuple<UTypes...>&&);
56
 
57
  template <class U1, class U2>
58
+ tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2
59
  template <class U1, class U2>
60
+ tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2
61
 
62
  // [tuple.swap], tuple swap
63
  void swap(tuple&) noexcept(see below);
64
  };
65
  }
 
68
  #### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
69
 
70
  For each `tuple` constructor, an exception is thrown only if the
71
  construction of one of the types in `Types` throws an exception.
72
 
73
+ The defaulted move and copy constructor, respectively, of `tuple` shall
74
+ be a `constexpr` function if and only if all required element-wise
75
+ initializations for copy and move, respectively, would satisfy the
76
+ requirements for a `constexpr` function. The defaulted move and copy
77
+ constructor of `tuple<>` shall be `constexpr` functions.
78
+
79
  In the constructor descriptions that follow, let i be in the range
80
  \[`0`, `sizeof...(Types)`) in order, Tᵢ be the iᵗʰ type in `Types`, and
81
  Uᵢ be the iᵗʰ type in a template parameter pack named `UTypes`, where
82
  indexing is zero-based.
83
 
 
88
  *Requires:* `is_default_constructible<`Tᵢ`>::value` is true for all i.
89
 
90
  *Effects:* Value initializes each element.
91
 
92
  ``` cpp
93
+ constexpr explicit tuple(const Types&...);
94
  ```
95
 
96
  *Requires:* `is_copy_constructible<`Tᵢ`>::value` is true for all i.
97
 
98
  *Effects:* Initializes each element with the value of the corresponding
99
  parameter.
100
 
101
  ``` cpp
102
  template <class... UTypes>
103
+ constexpr explicit tuple(UTypes&&... u);
104
  ```
105
 
106
  *Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
107
  `is_constructible<`Tᵢ`, `Uᵢ`&&>::value` is `true` for all i.
108
 
 
130
 
131
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
132
  `std::forward<`Tᵢ`>(get<`i`>(u))`.
133
 
134
  ``` cpp
135
+ template <class... UTypes> constexpr tuple(const tuple<UTypes...>& u);
136
  ```
137
 
138
  *Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
139
  `is_constructible<`Tᵢ`, const `Uᵢ`&>::value` is `true` for all i.
140
 
 
143
 
144
  This constructor shall not participate in overload resolution unless
145
  `const `Uᵢ`&` is implicitly convertible to Tᵢ for all i.
146
 
147
  ``` cpp
148
+ template <class... UTypes> constexpr tuple(tuple<UTypes...>&& u);
149
  ```
150
 
151
  *Requires:* `sizeof...(Types)` `==` `sizeof...(UTypes)`.
152
  `is_constructible<`Tᵢ`, `Uᵢ`&&>::value` is `true` for all i.
153
 
 
157
  This constructor shall not participate in overload resolution unless
158
  each type in `UTypes` is implicitly convertible to its corresponding
159
  type in `Types`.
160
 
161
  ``` cpp
162
+ template <class U1, class U2> constexpr tuple(const pair<U1, U2>& u);
163
  ```
164
 
165
  *Requires:* `sizeof...(Types) == 2`.
166
  `is_constructible<`T₀`, const U1&>::value` is `true` for the first type
167
  T₀ in `Types` and `is_constructible<`T₁`, const U2&>::value` is `true`
 
173
  This constructor shall not participate in overload resolution unless
174
  `const U1&` is implicitly convertible to T₀ and `const U2&` is
175
  implicitly convertible to T₁.
176
 
177
  ``` cpp
178
+ template <class U1, class U2> constexpr tuple(pair<U1, U2>&& u);
179
  ```
180
 
181
  *Requires:* `sizeof...(Types) == 2`.
182
  `is_constructible<`T₀`, U1&&>::value` is `true` for the first type T₀ in
183
  `Types` and `is_constructible<`T₁`, U2&&>::value` is `true` for the
 
326
 
327
  ``` cpp
328
  noexcept(swap(declval<Tᵢ&>>(), declval<Tᵢ&>()))
329
  ```
330
 
331
+ where T is the iᵗʰ type in `Types`.
332
 
333
  *Requires:* Each element in `*this` shall be swappable
334
  with ([[swappable.requirements]]) the corresponding element in `rhs`.
335
 
336
  *Effects:* Calls `swap` for each element in `*this` and its
 
347
  `sizeof...(UTypes)`) in order and Uⱼ be the jᵗʰ type in a template
348
  parameter pack named `UTypes`, where indexing is zero-based.
349
 
350
  ``` cpp
351
  template<class... Types>
352
+ constexpr tuple<VTypes...> make_tuple(Types&&... t);
353
  ```
354
 
355
+ Let Uᵢ be `decay_t<`Tᵢ`>` for each Tᵢ in `Types`. Then each Vᵢ in
356
  `VTypes` is `X&` if Uᵢ equals `reference_wrapper<X>`, otherwise Vᵢ is
357
  Uᵢ.
358
 
359
  *Returns:* `tuple<VTypes...>(std::forward<Types>(t)...)`.
360
 
 
369
  tuple<int, int&, const float&>
370
  ```
371
 
372
  ``` cpp
373
  template<class... Types>
374
+ constexpr tuple<Types&&...> forward_as_tuple(Types&&... t) noexcept;
375
  ```
376
 
377
  *Effects:* Constructs a tuple of references to the arguments in `t`
378
  suitable for forwarding as arguments to a function. Because the result
379
  may contain references to temporary variables, a program shall ensure
 
383
 
384
  *Returns:* `tuple<Types&&...>(std::forward<Types>(t)...)`
385
 
386
  ``` cpp
387
  template<class... Types>
388
+ constexpr tuple<Types&...> tie(Types&... t) noexcept;
389
  ```
390
 
391
+ *Returns:* `tuple<Types&...>(t...)`. When an argument in `t` is
392
+ `ignore`, assigning any value to the corresponding tuple element has no
393
+ effect.
394
 
395
  `tie` functions allow one to create tuples that unpack tuples into
396
  variables. `ignore` can be used for elements that are not needed:
397
 
398
  ``` cpp
 
401
  // i == 42, s == "C++"
402
  ```
403
 
404
  ``` cpp
405
  template <class... Tuples>
406
+ constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
407
  ```
408
 
409
  In the following paragraphs, let Tᵢ be the iᵗʰ type in `Tuples`, Uᵢ be
410
+ `remove_reference_t<Ti>`, and tpᵢ be the iᵗʰ parameter in the function
411
+ parameter pack `tpls`, where all indexing is zero-based.
412
 
413
  *Requires:* For all i, Uᵢ shall be the type cvᵢ `tuple<`Argsᵢ...`>`,
414
  where cvᵢ is the (possibly empty) iᵗʰ cv-qualifier-seq and Argsᵢ is the
415
  parameter pack representing the element types in Uᵢ. Let {Aᵢₖ} be the
416
  kᵢᵗʰ type in Argsᵢ. For all Aᵢₖ the following requirements shall be
 
433
  pack `Tuples` that support the `tuple`-like protocol, such as `pair` and
434
  `array`.
435
 
436
  #### Tuple helper classes <a id="tuple.helper">[[tuple.helper]]</a>
437
 
438
+ ``` cpp
439
+ template <class T> struct tuple_size;
440
+ ```
441
+
442
+ *Remarks:* All specializations of `tuple_size<T>` shall meet the
443
+ `UnaryTypeTrait` requirements ([[meta.rqmts]]) with a
444
+ `BaseCharacteristic` of `integral_constant<size_t, N>` for some `N`.
445
+
446
  ``` cpp
447
  template <class... Types>
448
  class tuple_size<tuple<Types...> >
449
  : public integral_constant<size_t, sizeof...(Types)> { };
450
  ```
 
472
  Let *TS* denote `tuple_size<T>` of the cv-unqualified type `T`. Then
473
  each of the three templates shall meet the `UnaryTypeTrait`
474
  requirements ([[meta.rqmts]]) with a `BaseCharacteristic` of
475
 
476
  ``` cpp
477
+ integral_constant<size_t, TS::value>
478
  ```
479
 
480
  ``` cpp
481
  template <size_t I, class T> class tuple_element<I, const T>;
482
  template <size_t I, class T> class tuple_element<I, volatile T>;
 
486
  Let *TE* denote `tuple_element<I, T>` of the cv-unqualified type `T`.
487
  Then each of the three templates shall meet the `TransformationTrait`
488
  requirements ([[meta.rqmts]]) with a member typedef `type` that names
489
  the following type:
490
 
491
+ - for the first specialization, `add_const_t<`*`TE`*`::type>`,
492
+ - for the second specialization, `add_volatile_t<`*`TE`*`::type>`, and
493
+ - for the third specialization, `add_cv_t<`*`TE`*`::type>`.
 
494
 
495
  #### Element access <a id="tuple.elem">[[tuple.elem]]</a>
496
 
497
  ``` cpp
498
  template <size_t I, class... Types>
499
+ constexpr tuple_element_t<I, tuple<Types...> >& get(tuple<Types...>& t) noexcept;
500
  ```
501
 
502
  *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
503
  out of bounds.
504
 
505
  *Returns:* A reference to the `I`th element of `t`, where indexing is
506
  zero-based.
507
 
508
  ``` cpp
509
+ template <size_t I, class... Types>
510
+ constexpr tuple_element_t<I, tuple<Types...> >&& get(tuple<Types...>&& t) noexcept;
511
  ```
512
 
513
  *Effects:* Equivalent to
514
  `return std::forward<typename tuple_element<I, tuple<Types...> >`
515
  `::type&&>(get<I>(t));`
 
518
  is `X&`, not `X&&`. However, if the element type is a non-reference type
519
  `T`, the return type is `T&&`.
520
 
521
  ``` cpp
522
  template <size_t I, class... Types>
523
+ constexpr tuple_element_t<I, tuple<Types...> > const& get(const tuple<Types...>& t) noexcept;
524
  ```
525
 
526
  *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
527
  out of bounds.
528
 
 
533
  the return type is `X&`, not `const X&`. However, if the element type is
534
  non-reference type `T`, the return type is `const T&`. This is
535
  consistent with how constness is defined to work for member variables of
536
  reference type.
537
 
538
+ ``` cpp
539
+ template <class T, class... Types>
540
+ constexpr T& get(tuple<Types...>& t) noexcept;
541
+ template <class T, class... Types>
542
+ constexpr T&& get(tuple<Types...>&& t) noexcept;
543
+ template <class T, class... Types>
544
+ constexpr const T& get(const tuple<Types...>& t) noexcept;
545
+ ```
546
+
547
+ *Requires:* The type `T` occurs exactly once in `Types...`. Otherwise,
548
+ the program is ill-formed.
549
+
550
+ *Returns:* A reference to the element of `t` corresponding to the type
551
+ `T` in `Types...`.
552
+
553
+ ``` cpp
554
+ const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
555
+ const int &i1 = get<int>(t); // OK. Not ambiguous. i1 == 1
556
+ const int &i2 = get<const int>(t); // OK. Not ambiguous. i2 == 2
557
+ const double &d = get<double>(t); // ERROR. ill-formed
558
+ ```
559
+
560
  The reason `get` is a nonmember function is that if this functionality
561
  had been provided as a member function, code where the type depended on
562
  a template parameter would have required using the `template` keyword.
563
 
564
  #### Relational operators <a id="tuple.rel">[[tuple.rel]]</a>
565
 
566
  ``` cpp
567
  template<class... TTypes, class... UTypes>
568
+ constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
569
  ```
570
 
571
+ *Requires:* For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`,
572
  `get<i>(t) == get<i>(u)` is a valid expression returning a type that is
573
  convertible to `bool`. `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
574
 
575
+ *Returns:* `true` if `get<i>(t) == get<i>(u)` for all `i`, otherwise
576
+ `false`. For any two zero-length tuples `e` and `f`, `e == f` returns
577
+ `true`.
578
 
579
  *Effects:* The elementary comparisons are performed in order from the
580
  zeroth index upwards. No comparisons or element accesses are performed
581
  after the first equality comparison that evaluates to `false`.
582
 
583
  ``` cpp
584
  template<class... TTypes, class... UTypes>
585
+ constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
586
  ```
587
 
588
+ *Requires:* For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`,
589
  `get<i>(t) < get<i>(u)` and `get<i>(u) < get<i>(t)` are valid
590
  expressions returning types that are convertible to `bool`.
591
  `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
592
 
593
  *Returns:* The result of a lexicographical comparison between `t` and
 
597
  element of `r`. For any two zero-length tuples `e` and `f`, `e < f`
598
  returns `false`.
599
 
600
  ``` cpp
601
  template<class... TTypes, class... UTypes>
602
+ constexpr bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
603
  ```
604
 
605
  *Returns:* `!(t == u)`.
606
 
607
  ``` cpp
608
  template<class... TTypes, class... UTypes>
609
+ constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
610
  ```
611
 
612
  *Returns:* `u < t`.
613
 
614
  ``` cpp
615
  template<class... TTypes, class... UTypes>
616
+ constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
617
  ```
618
 
619
  *Returns:* `!(u < t)`
620
 
621
  ``` cpp
622
  template<class... TTypes, class... UTypes>
623
+ constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
624
  ```
625
 
626
  *Returns:* `!(t < u)`
627
 
628
  The above definitions for comparison operators do not require `tₜₐᵢₗ`