From Jason Turner

[tuple.tuple]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp33pp8d0b/{from.md → to.md} +345 -228
tmp/tmp33pp8d0b/{from.md → to.md} RENAMED
@@ -3,49 +3,48 @@
3
  ``` cpp
4
  namespace std {
5
  template <class... Types>
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>
32
- tuple(allocator_arg_t, const Alloc& a, const Types&...);
33
  template <class Alloc, class... UTypes>
34
- tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
35
  template <class Alloc>
36
  tuple(allocator_arg_t, const Alloc& a, const tuple&);
37
  template <class Alloc>
38
  tuple(allocator_arg_t, const Alloc& a, tuple&&);
39
  template <class Alloc, class... UTypes>
40
- tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
41
  template <class Alloc, class... UTypes>
42
- tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
43
  template <class Alloc, class U1, class U2>
44
- tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
45
  template <class Alloc, class U1, class U2>
46
- tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
47
 
48
  // [tuple.assign], tuple assignment
49
  tuple& operator=(const tuple&);
50
  tuple& operator=(tuple&&) noexcept(see below);
51
 
@@ -60,158 +59,194 @@ namespace std {
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
  }
66
  ```
67
 
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
 
84
  ``` cpp
85
- constexpr tuple();
86
  ```
87
 
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
-
109
  *Effects:* Initializes the elements in the tuple with the corresponding
110
  value in `std::forward<UTypes>(u)`.
111
 
112
- This constructor shall not participate in overload resolution unless
113
- each type in `UTypes` is implicitly convertible to its corresponding
114
- type in `Types`.
 
 
115
 
116
  ``` cpp
117
  tuple(const tuple& u) = default;
118
  ```
119
 
120
- *Requires:* `is_copy_constructible<`Tᵢ`>::value` is `true` for all i.
121
 
122
  *Effects:* Initializes each element of `*this` with the corresponding
123
  element of `u`.
124
 
125
  ``` cpp
126
  tuple(tuple&& u) = default;
127
  ```
128
 
129
- *Requires:* `is_move_constructible<`Tᵢ`>::value` is `true` for all i.
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
-
141
- *Effects:* Constructs each element of `*this` with the corresponding
142
  element of `u`.
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
-
154
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
155
- `std::forward<`Uᵢ`>(get<`i`>(u))`.
156
 
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`
168
- for the second type T₁ in `Types`.
169
-
170
- *Effects:* Constructs the first element with `u.first` and the second
171
  element with `u.second`.
172
 
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
184
- second type T₁ in `Types`.
185
-
186
  *Effects:* Initializes the first element with
187
  `std::forward<U1>(u.first)` and the second element with
188
  `std::forward<U2>(u.second)`.
189
 
190
- This constructor shall not participate in overload resolution unless
191
- `U1` is implicitly convertible to T₀ and `U2` is implicitly convertible
192
- to T₁.
 
 
 
 
193
 
194
  ``` cpp
195
  template <class Alloc>
196
  tuple(allocator_arg_t, const Alloc& a);
197
  template <class Alloc>
198
- tuple(allocator_arg_t, const Alloc& a, const Types&...);
199
  template <class Alloc, class... UTypes>
200
- tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
201
  template <class Alloc>
202
  tuple(allocator_arg_t, const Alloc& a, const tuple&);
203
  template <class Alloc>
204
  tuple(allocator_arg_t, const Alloc& a, tuple&&);
205
  template <class Alloc, class... UTypes>
206
- tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
207
  template <class Alloc, class... UTypes>
208
- tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
209
  template <class Alloc, class U1, class U2>
210
- tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
211
  template <class Alloc, class U1, class U2>
212
- tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
213
  ```
214
 
215
  *Requires:* `Alloc` shall meet the requirements for an
216
  `Allocator` ([[allocator.requirements]]).
217
 
@@ -222,240 +257,300 @@ construction ([[allocator.uses.construction]]).
222
  #### Assignment <a id="tuple.assign">[[tuple.assign]]</a>
223
 
224
  For each `tuple` assignment operator, an exception is thrown only if the
225
  assignment of one of the types in `Types` throws an exception. In the
226
  function descriptions that follow, let i be in the range \[`0`,
227
- `sizeof...(Types)`) in order, Tᵢ be the iᵗʰ type in `Types`, and Uᵢ be
228
- the iᵗʰ type in a template parameter pack named `UTypes`, where indexing
229
- is zero-based.
230
 
231
  ``` cpp
232
  tuple& operator=(const tuple& u);
233
  ```
234
 
235
- *Requires:* `is_copy_assignable<`Tᵢ`>::value` is `true` for all i.
236
-
237
  *Effects:* Assigns each element of `u` to the corresponding element of
238
  `*this`.
239
 
240
- *Returns:* `*this`
 
 
 
241
 
242
  ``` cpp
243
  tuple& operator=(tuple&& u) noexcept(see below);
244
  ```
245
 
246
- The expression inside `noexcept` is equivalent to the logical
 
 
 
 
 
 
247
  <span class="smallcaps">and</span> of the following expressions:
248
 
249
  ``` cpp
250
- is_nothrow_move_assignable<Tᵢ>::value
251
  ```
252
 
253
  where Tᵢ is the iᵗʰ type in `Types`.
254
 
255
- *Requires:* `is_move_assignable<`Tᵢ`>::value` is `true` for all i.
256
-
257
- *Effects:* For all i, assigns `std::forward<`Tᵢ`>(get<`i`>(u))` to
258
- `get<`i`>(*this)`.
259
-
260
  *Returns:* `*this`.
261
 
262
  ``` cpp
263
- template <class... UTypes>
264
- tuple& operator=(const tuple<UTypes...>& u);
265
  ```
266
 
267
- *Requires:* `sizeof...(Types) == sizeof...(UTypes)` and
268
- `is_assignable<`Tᵢ`&, const `Uᵢ`&>::value` is `true` for all i.
269
-
270
  *Effects:* Assigns each element of `u` to the corresponding element of
271
  `*this`.
272
 
273
- *Returns:* `*this`
 
 
 
 
274
 
275
  ``` cpp
276
- template <class... UTypes>
277
- tuple& operator=(tuple<UTypes...>&& u);
278
  ```
279
 
280
- *Requires:* `is_assignable<Ti&, Ui&&>::value == true` for all `i`.
281
- `sizeof...(Types)` `==`
282
- `sizeof...(UTypes)`.
283
-
284
- *Effects:* For all i, assigns `std::forward<`Uᵢ`>(get<`i`)>(u))` to
285
  `get<`i`>(*this)`.
286
 
 
 
 
 
287
  *Returns:* `*this`.
288
 
289
  ``` cpp
290
  template <class U1, class U2> tuple& operator=(const pair<U1, U2>& u);
291
  ```
292
 
293
- *Requires:* `sizeof...(Types) == 2`.
294
- `is_assignable<`T₀`&, const U1&>::value` is `true` for the first type T₀
295
- in `Types` and `is_assignable<`T₁`&, const U2&>::value` is `true` for
296
- the second type T₁ in `Types`.
297
-
298
  *Effects:* Assigns `u.first` to the first element of `*this` and
299
  `u.second` to the second element of `*this`.
300
 
301
- *Returns:* `*this`
 
 
 
 
 
 
302
 
303
  ``` cpp
304
  template <class U1, class U2> tuple& operator=(pair<U1, U2>&& u);
305
  ```
306
 
307
- *Requires:* `sizeof...(Types) == 2`. `is_assignable<`T₀`&, U1&&>::value`
308
- is `true` for the first type T₀ in `Types` and
309
- `is_assignable<`T₁`&, U2&&>::value` is `true` for the second type T₁ in
310
- `Types`.
311
-
312
  *Effects:* Assigns `std::forward<U1>(u.first)` to the first element of
313
  `*this` and
314
  `std::forward<U2>(u.second)` to the second element of `*this`.
315
 
 
 
 
 
 
 
316
  *Returns:* `*this`.
317
 
318
  #### `swap` <a id="tuple.swap">[[tuple.swap]]</a>
319
 
320
  ``` cpp
321
  void swap(tuple& rhs) noexcept(see below);
322
  ```
323
 
324
- The expression inside `noexcept` is equivalent to the logical
325
- <span class="smallcaps">and</span> of the following expressions:
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
337
  corresponding element in `rhs`.
338
 
 
 
 
 
 
 
 
 
 
339
  *Throws:* Nothing unless one of the element-wise `swap` calls throws an
340
  exception.
341
 
342
  #### Tuple creation functions <a id="tuple.creation">[[tuple.creation]]</a>
343
 
344
- In the function descriptions that follow, let i be in the range \[`0`,
345
- `sizeof...(TTypes)`) in order and let Tbe the iᵗʰ type in a template
346
- parameter pack named `TTypes`; let j be in the range \[`0`,
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
 
361
  ``` cpp
362
  int i; float j;
363
  make_tuple(1, ref(i), cref(j))
364
  ```
365
 
366
- creates a tuple of type
367
 
368
- ``` cpp
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
380
  that the return value of this function does not outlive any of its
381
- arguments. (e.g., the program should typically not store the result in a
382
  named variable).
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
399
  int i; std::string s;
400
  tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
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
417
- satisfied: If Tᵢ is deduced as an lvalue reference type, then
418
- `is_constructible<`Aᵢₖ`, `cvᵢ` `Aᵢₖ`&>::value == true`, otherwise
419
- `is_constructible<`Aᵢₖ`, `cvᵢ Aᵢₖ`&&>::value == true`.
420
 
421
- *Remarks:* The types in *`Ctypes`* shall be equal to the ordered
422
- sequence of the extended types Args₀`..., `Args₁`...,` ... Argsₙ₋₁`...`,
423
- where n is equal to `sizeof...(Tuples)`. Let eᵢ`...` be the iᵗʰ ordered
424
- sequence of tuple elements of the resulting `tuple` object corresponding
425
- to the type sequence Argsᵢ.
 
 
 
 
426
 
427
  *Returns:* A `tuple` object constructed by initializing the kᵢᵗʰ type
428
- element eᵢₖ in eᵢ`...` with
429
- `get<`kᵢ`>(std::forward<`Tᵢ`>(`tpᵢ`))` for each valid kᵢ and each group
430
- eᵢ in order.
431
 
432
- *Note:* An implementation may support additional types in the parameter
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
  ```
451
 
452
  ``` cpp
453
  template <size_t I, class... Types>
454
  class tuple_element<I, tuple<Types...>> {
455
  public:
456
- typedef TI type;
457
  };
458
  ```
459
 
460
  *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
461
  out of bounds.
@@ -467,101 +562,119 @@ is zero-based.
467
  template <class T> class tuple_size<const T>;
468
  template <class T> class tuple_size<volatile T>;
469
  template <class T> class tuple_size<const volatile T>;
470
  ```
471
 
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>;
483
  template <size_t I, class T> class tuple_element<I, const volatile T>;
484
  ```
485
 
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));`
516
-
517
- *Note:* if a `T` in `Types` is some reference type `X&`, the return type
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
-
529
- *Returns:* A const reference to the `I`th element of `t`, where indexing
530
- is zero-based.
531
-
532
- Constness is shallow. If a `T` in `Types` is some reference type `X&`,
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>
@@ -584,11 +697,11 @@ after the first equality comparison that evaluates to `false`.
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
594
  `u`. The result is defined as:
@@ -614,24 +727,25 @@ template<class... TTypes, class... UTypes>
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ₜₐᵢₗ`
629
- (or `uₜₐᵢₗ`) to be constructed. It may not even be possible, as `t` and
630
- `u` are not required to be copy constructible. Also, all comparison
631
- operators are short circuited; they do not perform element accesses
632
- beyond what is required to determine the result of the comparison.
 
633
 
634
  #### Tuple traits <a id="tuple.traits">[[tuple.traits]]</a>
635
 
636
  ``` cpp
637
  template <class... Types, class Alloc>
@@ -639,24 +753,27 @@ template <class... Types, class Alloc>
639
  ```
640
 
641
  *Requires:* `Alloc` shall be an
642
  `Allocator` ([[allocator.requirements]]).
643
 
644
- Specialization of this trait informs other library components that
645
- `tuple` can be constructed with an allocator, even though it does not
646
- have a nested `allocator_type`.
647
 
648
  #### Tuple specialized algorithms <a id="tuple.special">[[tuple.special]]</a>
649
 
650
  ``` cpp
651
  template <class... Types>
652
  void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
653
  ```
654
 
655
- The expression inside `noexcept` is equivalent to:
 
 
 
656
 
657
  ``` cpp
658
  noexcept(x.swap(y))
659
  ```
660
 
661
- *Effects:* `x.swap(y)`
662
 
 
3
  ``` cpp
4
  namespace std {
5
  template <class... Types>
6
  class tuple {
7
  public:
 
8
  // [tuple.cnstr], tuple construction
9
+ \EXPLICIT constexpr tuple();
10
+ \EXPLICIT constexpr tuple(const Types&...); // only if sizeof...(Types) >= 1
11
  template <class... UTypes>
12
+ \EXPLICIT constexpr tuple(UTypes&&...); // only if sizeof...(Types) >= 1
13
 
14
  tuple(const tuple&) = default;
15
  tuple(tuple&&) = default;
16
 
17
  template <class... UTypes>
18
+ \EXPLICIT constexpr tuple(const tuple<UTypes...>&);
19
  template <class... UTypes>
20
+ \EXPLICIT constexpr tuple(tuple<UTypes...>&&);
21
 
22
  template <class U1, class U2>
23
+ \EXPLICIT constexpr tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2
24
  template <class U1, class U2>
25
+ \EXPLICIT constexpr tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2
26
 
27
  // allocator-extended constructors
28
  template <class Alloc>
29
  tuple(allocator_arg_t, const Alloc& a);
30
  template <class Alloc>
31
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const Types&...);
32
  template <class Alloc, class... UTypes>
33
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
34
  template <class Alloc>
35
  tuple(allocator_arg_t, const Alloc& a, const tuple&);
36
  template <class Alloc>
37
  tuple(allocator_arg_t, const Alloc& a, tuple&&);
38
  template <class Alloc, class... UTypes>
39
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
40
  template <class Alloc, class... UTypes>
41
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
42
  template <class Alloc, class U1, class U2>
43
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
44
  template <class Alloc, class U1, class U2>
45
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
46
 
47
  // [tuple.assign], tuple assignment
48
  tuple& operator=(const tuple&);
49
  tuple& operator=(tuple&&) noexcept(see below);
50
 
 
59
  tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2
60
 
61
  // [tuple.swap], tuple swap
62
  void swap(tuple&) noexcept(see below);
63
  };
64
+
65
+ template<class... UTypes>
66
+ tuple(UTypes...) -> tuple<UTypes...>;
67
+ template<class T1, class T2>
68
+ tuple(pair<T1, T2>) -> tuple<T1, T2>;
69
+ template<class Alloc, class... UTypes>
70
+ tuple(allocator_arg_t, Alloc, UTypes...) -> tuple<UTypes...>;
71
+ template<class Alloc, class T1, class T2>
72
+ tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>;
73
+ template<class Alloc, class... UTypes>
74
+ tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>;
75
  }
76
  ```
77
 
78
  #### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
79
 
80
  For each `tuple` constructor, an exception is thrown only if the
81
  construction of one of the types in `Types` throws an exception.
82
 
83
  The defaulted move and copy constructor, respectively, of `tuple` shall
84
+ be a constexpr function if and only if all required element-wise
85
  initializations for copy and move, respectively, would satisfy the
86
+ requirements for a constexpr function. The defaulted move and copy
87
+ constructor of `tuple<>` shall be constexpr functions.
88
+
89
+ The destructor of tuple shall be a trivial destructor if
90
+ `(is_trivially_destructible_v<Types> && ...)` is `true`.
91
 
92
  In the constructor descriptions that follow, let i be in the range
93
+ \[`0`, `sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`,
94
+ and `Uᵢ` be the iᵗʰ type in a template parameter pack named `UTypes`,
95
+ where indexing is zero-based.
96
 
97
  ``` cpp
98
+ \EXPLICIT constexpr tuple();
99
  ```
100
 
101
+ *Effects:* Value-initializes each element.
102
 
103
+ *Remarks:* This constructor shall not participate in overload resolution
104
+ unless `is_default_constructible_v<``Tᵢ``>` is `true` for all i.
105
+
106
+ [*Note 1*: This behavior can be implemented by a constructor template
107
+ with default template arguments. — *end note*]
108
+
109
+ The constructor is explicit if and only if `Tᵢ` is not implicitly
110
+ default-constructible for at least one i.
111
+
112
+ [*Note 2*: This behavior can be implemented with a trait that checks
113
+ whether a `const ``Tᵢ``&` can be initialized with `{}`. — *end note*]
114
 
115
  ``` cpp
116
+ \EXPLICIT constexpr tuple(const Types&...);
117
  ```
118
 
 
 
119
  *Effects:* Initializes each element with the value of the corresponding
120
  parameter.
121
 
122
+ *Remarks:* This constructor shall not participate in overload resolution
123
+ unless `sizeof...(Types) >= 1` and `is_copy_constructible_v<``Tᵢ``>` is
124
+ `true` for all i. The constructor is explicit if and only if
125
+ `is_convertible_v<const ``Tᵢ``&, ``Tᵢ``>` is `false` for at least one i.
126
+
127
  ``` cpp
128
+ template <class... UTypes> \EXPLICIT constexpr tuple(UTypes&&... u);
 
129
  ```
130
 
 
 
 
131
  *Effects:* Initializes the elements in the tuple with the corresponding
132
  value in `std::forward<UTypes>(u)`.
133
 
134
+ *Remarks:* This constructor shall not participate in overload resolution
135
+ unless `sizeof...(Types)` `==` `sizeof...(UTypes)` and
136
+ `sizeof...(Types) >= 1` and `is_constructible_v<``Tᵢ``, ``Uᵢ``&&>` is
137
+ `true` for all i. The constructor is explicit if and only if
138
+ `is_convertible_v<``Uᵢ``&&, ``Tᵢ``>` is `false` for at least one i.
139
 
140
  ``` cpp
141
  tuple(const tuple& u) = default;
142
  ```
143
 
144
+ *Requires:* `is_copy_constructible_v<``Tᵢ``>` is `true` for all i.
145
 
146
  *Effects:* Initializes each element of `*this` with the corresponding
147
  element of `u`.
148
 
149
  ``` cpp
150
  tuple(tuple&& u) = default;
151
  ```
152
 
153
+ *Requires:* `is_move_constructible_v<``Tᵢ``>` is `true` for all i.
154
 
155
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
156
+ `std::forward<``Tᵢ``>(get<`i`>(u))`.
157
 
158
  ``` cpp
159
+ template <class... UTypes> \EXPLICIT constexpr tuple(const tuple<UTypes...>& u);
160
  ```
161
 
162
+ *Effects:* Initializes each element of `*this` with the corresponding
 
 
 
163
  element of `u`.
164
 
165
+ *Remarks:* This constructor shall not participate in overload resolution
166
+ unless
167
+
168
+ - `sizeof...(Types)` `==` `sizeof...(UTypes)` and
169
+ - `is_constructible_v<``Tᵢ``, const ``Uᵢ``&>` is `true` for all i, and
170
+ - `sizeof...(Types) != 1`, or (when `Types...` expands to `T` and
171
+ `UTypes...` expands to `U`)
172
+ `!is_convertible_v<const tuple<U>&, T> && !is_constructible_v<T, const tuple<U>&>&& !is_same_v<T, U>`
173
+ is `true`.
174
+
175
+ The constructor is explicit if and only if
176
+ `is_convertible_v<const ``Uᵢ``&, ``Tᵢ``>` is `false` for at least one i.
177
 
178
  ``` cpp
179
+ template <class... UTypes> \EXPLICIT constexpr tuple(tuple<UTypes...>&& u);
180
  ```
181
 
 
 
 
182
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
183
+ `std::forward<``Uᵢ``>(get<`i`>(u))`.
184
 
185
+ *Remarks:* This constructor shall not participate in overload resolution
186
+ unless
187
+
188
+ - `sizeof...(Types)` `==` `sizeof...(UTypes)`, and
189
+ - `is_constructible_v<``Tᵢ``, ``Uᵢ``&&>` is `true` for all i, and
190
+ - `sizeof...(Types) != 1`, or (when `Types...` expands to `T` and
191
+ `UTypes...` expands to `U`)
192
+ `!is_convertible_v<tuple<U>, T> && !is_constructible_v<T, tuple<U>> &&!is_same_v<T, U>`
193
+ is `true`.
194
+
195
+ The constructor is explicit if and only if
196
+ `is_convertible_v<``Uᵢ``&&, ``Tᵢ``>` is `false` for at least one i.
197
 
198
  ``` cpp
199
+ template <class U1, class U2> \EXPLICIT constexpr tuple(const pair<U1, U2>& u);
200
  ```
201
 
202
+ *Effects:* Initializes the first element with `u.first` and the second
 
 
 
 
 
203
  element with `u.second`.
204
 
205
+ *Remarks:* This constructor shall not participate in overload resolution
206
+ unless `sizeof...(Types) == 2`, `is_constructible_v<``T₀``, const U1&>`
207
+ is `true` and `is_constructible_v<``T₁``, const U2&>` is `true`.
208
+
209
+ The constructor is explicit if and only if
210
+ `is_convertible_v<const U1&, ``T₀``>` is `false` or
211
+ `is_convertible_v<const U2&, ``T₁``>` is `false`.
212
 
213
  ``` cpp
214
+ template <class U1, class U2> \EXPLICIT constexpr tuple(pair<U1, U2>&& u);
215
  ```
216
 
 
 
 
 
 
217
  *Effects:* Initializes the first element with
218
  `std::forward<U1>(u.first)` and the second element with
219
  `std::forward<U2>(u.second)`.
220
 
221
+ *Remarks:* This constructor shall not participate in overload resolution
222
+ unless `sizeof...(Types) == 2`, `is_constructible_v<``T₀``, U1&&>` is
223
+ `true` and `is_constructible_v<``T₁``, U2&&>` is `true`.
224
+
225
+ The constructor is explicit if and only if
226
+ `is_convertible_v<U1&&, ``T₀``>` is `false` or
227
+ `is_convertible_v<U2&&, ``T₁``>` is `false`.
228
 
229
  ``` cpp
230
  template <class Alloc>
231
  tuple(allocator_arg_t, const Alloc& a);
232
  template <class Alloc>
233
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const Types&...);
234
  template <class Alloc, class... UTypes>
235
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
236
  template <class Alloc>
237
  tuple(allocator_arg_t, const Alloc& a, const tuple&);
238
  template <class Alloc>
239
  tuple(allocator_arg_t, const Alloc& a, tuple&&);
240
  template <class Alloc, class... UTypes>
241
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
242
  template <class Alloc, class... UTypes>
243
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
244
  template <class Alloc, class U1, class U2>
245
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
246
  template <class Alloc, class U1, class U2>
247
+ \EXPLICIT tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
248
  ```
249
 
250
  *Requires:* `Alloc` shall meet the requirements for an
251
  `Allocator` ([[allocator.requirements]]).
252
 
 
257
  #### Assignment <a id="tuple.assign">[[tuple.assign]]</a>
258
 
259
  For each `tuple` assignment operator, an exception is thrown only if the
260
  assignment of one of the types in `Types` throws an exception. In the
261
  function descriptions that follow, let i be in the range \[`0`,
262
+ `sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`, and `Uᵢ`
263
+ be the iᵗʰ type in a template parameter pack named `UTypes`, where
264
+ indexing is zero-based.
265
 
266
  ``` cpp
267
  tuple& operator=(const tuple& u);
268
  ```
269
 
 
 
270
  *Effects:* Assigns each element of `u` to the corresponding element of
271
  `*this`.
272
 
273
+ *Remarks:* This operator shall be defined as deleted unless
274
+ `is_copy_assignable_v<``Tᵢ``>` is `true` for all i.
275
+
276
+ *Returns:* `*this`.
277
 
278
  ``` cpp
279
  tuple& operator=(tuple&& u) noexcept(see below);
280
  ```
281
 
282
+ *Effects:* For all i, assigns `std::forward<``Tᵢ``>(get<`i`>(u))` to
283
+ `get<`i`>(*this)`.
284
+
285
+ *Remarks:* This operator shall be defined as deleted unless
286
+ `is_move_assignable_v<``Tᵢ``>` is `true` for all i.
287
+
288
+ *Remarks:* The expression inside `noexcept` is equivalent to the logical
289
  <span class="smallcaps">and</span> of the following expressions:
290
 
291
  ``` cpp
292
+ is_nothrow_move_assignable_v<Tᵢ>
293
  ```
294
 
295
  where Tᵢ is the iᵗʰ type in `Types`.
296
 
 
 
 
 
 
297
  *Returns:* `*this`.
298
 
299
  ``` cpp
300
+ template <class... UTypes> tuple& operator=(const tuple<UTypes...>& u);
 
301
  ```
302
 
 
 
 
303
  *Effects:* Assigns each element of `u` to the corresponding element of
304
  `*this`.
305
 
306
+ *Remarks:* This operator shall not participate in overload resolution
307
+ unless `sizeof...(Types) == sizeof...(UTypes)` and
308
+ `is_assignable_v<``Tᵢ``&, const ``Uᵢ``&>` is `true` for all i.
309
+
310
+ *Returns:* `*this`.
311
 
312
  ``` cpp
313
+ template <class... UTypes> tuple& operator=(tuple<UTypes...>&& u);
 
314
  ```
315
 
316
+ *Effects:* For all i, assigns `std::forward<``Uᵢ``>(get<`i`>(u))` to
 
 
 
 
317
  `get<`i`>(*this)`.
318
 
319
+ *Remarks:* This operator shall not participate in overload resolution
320
+ unless `is_assignable_v<``Tᵢ``&, ``Uᵢ``&&> == true` for all i and
321
+ `sizeof...(Types) == sizeof...(UTypes)`.
322
+
323
  *Returns:* `*this`.
324
 
325
  ``` cpp
326
  template <class U1, class U2> tuple& operator=(const pair<U1, U2>& u);
327
  ```
328
 
 
 
 
 
 
329
  *Effects:* Assigns `u.first` to the first element of `*this` and
330
  `u.second` to the second element of `*this`.
331
 
332
+ *Remarks:* This operator shall not participate in overload resolution
333
+ unless `sizeof...(Types) == 2` and `is_assignable_v<``T₀``&, const U1&>`
334
+ is `true` for the first type `T₀` in `Types` and
335
+ `is_assignable_v<``T₁``&, const U2&>` is `true` for the second type `T₁`
336
+ in `Types`.
337
+
338
+ *Returns:* `*this`.
339
 
340
  ``` cpp
341
  template <class U1, class U2> tuple& operator=(pair<U1, U2>&& u);
342
  ```
343
 
 
 
 
 
 
344
  *Effects:* Assigns `std::forward<U1>(u.first)` to the first element of
345
  `*this` and
346
  `std::forward<U2>(u.second)` to the second element of `*this`.
347
 
348
+ *Remarks:* This operator shall not participate in overload resolution
349
+ unless `sizeof...(Types) == 2` and `is_assignable_v<``T₀``&, U1&&>` is
350
+ `true` for the first type `T₀` in `Types` and
351
+ `is_assignable_v<``T₁``&, U2&&>` is `true` for the second type `T₁` in
352
+ `Types`.
353
+
354
  *Returns:* `*this`.
355
 
356
  #### `swap` <a id="tuple.swap">[[tuple.swap]]</a>
357
 
358
  ``` cpp
359
  void swap(tuple& rhs) noexcept(see below);
360
  ```
361
 
 
 
 
 
 
 
 
 
 
362
  *Requires:* Each element in `*this` shall be swappable
363
  with ([[swappable.requirements]]) the corresponding element in `rhs`.
364
 
365
  *Effects:* Calls `swap` for each element in `*this` and its
366
  corresponding element in `rhs`.
367
 
368
+ *Remarks:* The expression inside `noexcept` is equivalent to the logical
369
+ <span class="smallcaps">and</span> of the following expressions:
370
+
371
+ ``` cpp
372
+ is_nothrow_swappable_v<Tᵢ>
373
+ ```
374
+
375
+ where Tᵢ is the iᵗʰ type in `Types`.
376
+
377
  *Throws:* Nothing unless one of the element-wise `swap` calls throws an
378
  exception.
379
 
380
  #### Tuple creation functions <a id="tuple.creation">[[tuple.creation]]</a>
381
 
382
+ In the function descriptions that follow, the members of a parameter
383
+ pack `XTypes` are denoted by `X`for i in \[`0`,
384
+ `sizeof...(`*X*`Types)`) in order, where indexing is zero-based.
 
 
385
 
386
  ``` cpp
387
+ template<class... TTypes>
388
+ constexpr tuple<VTypes...> make_tuple(TTypes&&... t);
389
  ```
390
 
391
+ The pack `VTypes` is defined as follows. Let `U`ᵢ be `decay_t<T`ᵢ`>` for
392
+ each `T` in `TTypes`. If `U`is a specialization of
393
+ `reference_wrapper`, then `V`ᵢ in `VTypes` is `U``::type&`, otherwise
394
+ `V`ᵢ is `U`ᵢ.
395
 
396
+ *Returns:* `tuple<VTypes...>(std::forward<TTypes>(t)...)`.
397
+
398
+ [*Example 1*:
399
 
400
  ``` cpp
401
  int i; float j;
402
  make_tuple(1, ref(i), cref(j))
403
  ```
404
 
405
+ creates a tuple of type `tuple<int, int&, const float&>`.
406
 
407
+ *end example*]
 
 
408
 
409
  ``` cpp
410
+ template<class... TTypes>
411
+ constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&... t) noexcept;
412
  ```
413
 
414
  *Effects:* Constructs a tuple of references to the arguments in `t`
415
  suitable for forwarding as arguments to a function. Because the result
416
  may contain references to temporary variables, a program shall ensure
417
  that the return value of this function does not outlive any of its
418
+ arguments (e.g., the program should typically not store the result in a
419
  named variable).
420
 
421
+ *Returns:* `tuple<TTypes&&...>(std::forward<TTypes>(t)...)`.
422
 
423
  ``` cpp
424
+ template<class... TTypes>
425
+ constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
426
  ```
427
 
428
+ *Returns:* `tuple<TTypes&...>(t...)`. When an argument in `t` is
429
  `ignore`, assigning any value to the corresponding tuple element has no
430
  effect.
431
 
432
+ [*Example 2*:
433
+
434
  `tie` functions allow one to create tuples that unpack tuples into
435
  variables. `ignore` can be used for elements that are not needed:
436
 
437
  ``` cpp
438
  int i; std::string s;
439
  tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
440
  // i == 42, s == "C++"
441
  ```
442
 
443
+ — *end example*]
444
+
445
  ``` cpp
446
  template <class... Tuples>
447
  constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
448
  ```
449
 
450
+ In the following paragraphs, let `Tᵢ` be the iᵗʰ type in `Tuples`, `Uᵢ`
451
+ be `remove_reference_t<T`ᵢ`>`, and `tpᵢ` be the iᵗʰ parameter in the
452
+ function parameter pack `tpls`, where all indexing is zero-based.
453
 
454
+ *Requires:* For all i, `Uᵢ` shall be the type cvᵢ `tuple<``Argsᵢ``...>`,
455
+ where cvᵢ is the (possibly empty) iᵗʰ *cv-qualifier-seq* and `Argsᵢ` is
456
+ the parameter pack representing the element types in `Uᵢ`. Let `A_ik` be
457
+ the kᵗʰ type in `Argsᵢ`. For all `A_ik` the following requirements shall
458
+ be satisfied:
 
 
459
 
460
+ - If `Tᵢ` is deduced as an lvalue reference type, then
461
+ `is_constructible_v<``A_ik``, `cvᵢ `A_ik``&> == true`, otherwise
462
+ - `is_constructible_v<``A_ik``, `cv `A_ik``&&> == true`.
463
+
464
+ *Remarks:* The types in `CTypes` shall be equal to the ordered sequence
465
+ of the extended types `Args₀``..., ``Args₁``..., `…`, ``Args_n-1``...`,
466
+ where n is equal to `sizeof...(Tuples)`. Let `eᵢ``...` be the iᵗʰ
467
+ ordered sequence of tuple elements of the resulting `tuple` object
468
+ corresponding to the type sequence `Argsᵢ`.
469
 
470
  *Returns:* A `tuple` object constructed by initializing the kᵢᵗʰ type
471
+ element `e_ik` in `eᵢ``...` with
 
 
472
 
473
+ ``` cpp
474
+ get<kᵢ>(std::forward<$T_i$>($tp_i$))
475
+ ```
476
+
477
+ for each valid kᵢ and each group `eᵢ` in order.
478
+
479
+ [*Note 1*: An implementation may support additional types in the
480
+ parameter pack `Tuples` that support the `tuple`-like protocol, such as
481
+ `pair` and `array`. — *end note*]
482
+
483
+ #### Calling a function with a `tuple` of arguments <a id="tuple.apply">[[tuple.apply]]</a>
484
+
485
+ ``` cpp
486
+ template <class F, class Tuple>
487
+ constexpr decltype(auto) apply(F&& f, Tuple&& t);
488
+ ```
489
+
490
+ *Effects:* Given the exposition-only function:
491
+
492
+ ``` cpp
493
+ template <class F, class Tuple, size_t... I>
494
+ constexpr decltype(auto)
495
+ apply_impl(F&& f, Tuple&& t, index_sequence<I...>) { // exposition only
496
+ return INVOKE(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
497
+ }
498
+ ```
499
+
500
+ Equivalent to:
501
+
502
+ ``` cpp
503
+ return apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
504
+ make_index_sequence<tuple_size_v<decay_t<Tuple>>>{});
505
+ ```
506
+
507
+ ``` cpp
508
+ template <class T, class Tuple>
509
+ constexpr T make_from_tuple(Tuple&& t);
510
+ ```
511
+
512
+ *Effects:* Given the exposition-only function:
513
+
514
+ ``` cpp
515
+ template <class T, class Tuple, size_t... I>
516
+ constexpr T make_from_tuple_impl(Tuple&& t, index_sequence<I...>) { // exposition only
517
+ return T(get<I>(std::forward<Tuple>(t))...);
518
+ }
519
+ ```
520
+
521
+ Equivalent to:
522
+
523
+ ``` cpp
524
+ return make_from_tuple_impl<T>(forward<Tuple>(t),
525
+ make_index_sequence<tuple_size_v<decay_t<Tuple>>>{});
526
+ ```
527
+
528
+ [*Note 1*: The type of `T` must be supplied as an explicit template
529
+ parameter, as it cannot be deduced from the argument
530
+ list. — *end note*]
531
 
532
  #### Tuple helper classes <a id="tuple.helper">[[tuple.helper]]</a>
533
 
534
  ``` cpp
535
  template <class T> struct tuple_size;
536
  ```
537
 
538
+ *Remarks:* All specializations of `tuple_size` shall meet the
539
+ `UnaryTypeTrait` requirements ([[meta.rqmts]]) with a base
540
+ characteristic of `integral_constant<size_t, N>` for some `N`.
541
 
542
  ``` cpp
543
  template <class... Types>
544
+ class tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
 
545
  ```
546
 
547
  ``` cpp
548
  template <size_t I, class... Types>
549
  class tuple_element<I, tuple<Types...>> {
550
  public:
551
+ using type = TI;
552
  };
553
  ```
554
 
555
  *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
556
  out of bounds.
 
562
  template <class T> class tuple_size<const T>;
563
  template <class T> class tuple_size<volatile T>;
564
  template <class T> class tuple_size<const volatile T>;
565
  ```
566
 
567
+ Let *`TS`* denote `tuple_size<T>` of the cv-unqualified type `T`. If the
568
+ expression *`TS`*`::value` is well-formed when treated as an unevaluated
569
+ operand, then each of the three templates shall meet the
570
+ `UnaryTypeTrait` requirements ([[meta.rqmts]]) with a base
571
+ characteristic of
572
 
573
  ``` cpp
574
  integral_constant<size_t, TS::value>
575
  ```
576
 
577
+ Otherwise, they shall have no member `value`.
578
+
579
+ Access checking is performed as if in a context unrelated to *`TS`* and
580
+ `T`. Only the validity of the immediate context of the expression is
581
+ considered.
582
+
583
+ [*Note 1*: The compilation of the expression can result in side effects
584
+ such as the instantiation of class template specializations and function
585
+ template specializations, the generation of implicitly-defined
586
+ functions, and so on. Such side effects are not in the “immediate
587
+ context” and can result in the program being ill-formed. — *end note*]
588
+
589
+ In addition to being available via inclusion of the `<tuple>` header,
590
+ the three templates are available when either of the headers `<array>`
591
+ or `<utility>` are included.
592
+
593
  ``` cpp
594
  template <size_t I, class T> class tuple_element<I, const T>;
595
  template <size_t I, class T> class tuple_element<I, volatile T>;
596
  template <size_t I, class T> class tuple_element<I, const volatile T>;
597
  ```
598
 
599
+ Let *`TE`* denote `tuple_element_t<I, T>` of the cv-unqualified type
600
+ `T`. Then each of the three templates shall meet the
601
+ `TransformationTrait` requirements ([[meta.rqmts]]) with a member
602
+ typedef `type` that names the following type:
603
 
604
+ - for the first specialization, `add_const_t<`*`TE`*`>`,
605
+ - for the second specialization, `add_volatile_t<`*`TE`*`>`, and
606
+ - for the third specialization, `add_cv_t<`*`TE`*`>`.
607
+
608
+ In addition to being available via inclusion of the `<tuple>` header,
609
+ the three templates are available when either of the headers `<array>`
610
+ or `<utility>` are included.
611
 
612
  #### Element access <a id="tuple.elem">[[tuple.elem]]</a>
613
 
614
  ``` cpp
615
  template <size_t I, class... Types>
616
+ constexpr tuple_element_t<I, tuple<Types...>>&
617
+ get(tuple<Types...>& t) noexcept;
618
+ template <size_t I, class... Types>
619
+ constexpr tuple_element_t<I, tuple<Types...>>&&
620
+ get(tuple<Types...>&& t) noexcept; // Note A
621
+ template <size_t I, class... Types>
622
+ constexpr const tuple_element_t<I, tuple<Types...>>&
623
+ get(const tuple<Types...>& t) noexcept; // Note B
624
+ template <size_t I, class... Types>
625
+ constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
626
  ```
627
 
628
  *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
629
  out of bounds.
630
 
631
  *Returns:* A reference to the `I`th element of `t`, where indexing is
632
  zero-based.
633
 
634
+ [*Note 1*: \[Note A\]If a `T` in `Types` is some reference type `X&`,
635
+ the return type is `X&`, not `X&&`. However, if the element type is a
636
+ non-reference type `T`, the return type is `T&&`. *end note*]
637
+
638
+ [*Note 2*: \[Note B\]Constness is shallow. If a `T` in `Types` is some
639
+ reference type `X&`, the return type is `X&`, not `const X&`. However,
640
+ if the element type is a non-reference type `T`, the return type is
641
+ `const T&`. This is consistent with how constness is defined to work for
642
+ member variables of reference type. — *end note*]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
643
 
644
  ``` cpp
645
  template <class T, class... Types>
646
  constexpr T& get(tuple<Types...>& t) noexcept;
647
  template <class T, class... Types>
648
  constexpr T&& get(tuple<Types...>&& t) noexcept;
649
  template <class T, class... Types>
650
  constexpr const T& get(const tuple<Types...>& t) noexcept;
651
+ template <class T, class... Types>
652
+ constexpr const T&& get(const tuple<Types...>&& t) noexcept;
653
  ```
654
 
655
  *Requires:* The type `T` occurs exactly once in `Types...`. Otherwise,
656
  the program is ill-formed.
657
 
658
  *Returns:* A reference to the element of `t` corresponding to the type
659
  `T` in `Types...`.
660
 
661
+ [*Example 1*:
662
+
663
  ``` cpp
664
  const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
665
  const int& i1 = get<int>(t); // OK. Not ambiguous. i1 == 1
666
  const int& i2 = get<const int>(t); // OK. Not ambiguous. i2 == 2
667
  const double& d = get<double>(t); // ERROR. ill-formed
668
  ```
669
 
670
+ *end example*]
671
+
672
+ [*Note 1*: The reason `get` is a non-member function is that if this
673
+ functionality had been provided as a member function, code where the
674
+ type depended on a template parameter would have required using the
675
+ `template` keyword. — *end note*]
676
 
677
  #### Relational operators <a id="tuple.rel">[[tuple.rel]]</a>
678
 
679
  ``` cpp
680
  template<class... TTypes, class... UTypes>
 
697
  template<class... TTypes, class... UTypes>
698
  constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
699
  ```
700
 
701
  *Requires:* For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`,
702
+ both `get<i>(t) < get<i>(u)` and `get<i>(u) < get<i>(t)` are valid
703
  expressions returning types that are convertible to `bool`.
704
  `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
705
 
706
  *Returns:* The result of a lexicographical comparison between `t` and
707
  `u`. The result is defined as:
 
727
  ``` cpp
728
  template<class... TTypes, class... UTypes>
729
  constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
730
  ```
731
 
732
+ *Returns:* `!(u < t)`.
733
 
734
  ``` cpp
735
  template<class... TTypes, class... UTypes>
736
  constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
737
  ```
738
 
739
+ *Returns:* `!(t < u)`.
740
 
741
+ [*Note 1*: The above definitions for comparison functions do not
742
+ require `tₜₐᵢₗ` (or `uₜₐᵢₗ`) to be constructed. It may not even be
743
+ possible, as `t` and `u` are not required to be copy constructible.
744
+ Also, all comparison functions are short circuited; they do not perform
745
+ element accesses beyond what is required to determine the result of the
746
+ comparison. — *end note*]
747
 
748
  #### Tuple traits <a id="tuple.traits">[[tuple.traits]]</a>
749
 
750
  ``` cpp
751
  template <class... Types, class Alloc>
 
753
  ```
754
 
755
  *Requires:* `Alloc` shall be an
756
  `Allocator` ([[allocator.requirements]]).
757
 
758
+ [*Note 1*: Specialization of this trait informs other library
759
+ components that `tuple` can be constructed with an allocator, even
760
+ though it does not have a nested `allocator_type`. — *end note*]
761
 
762
  #### Tuple specialized algorithms <a id="tuple.special">[[tuple.special]]</a>
763
 
764
  ``` cpp
765
  template <class... Types>
766
  void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
767
  ```
768
 
769
+ *Remarks:* This function shall not participate in overload resolution
770
+ unless `is_swappable_v<``Tᵢ``>` is `true` for all i, where
771
+ 0 ≤ i < `sizeof...(Types)`. The expression inside `noexcept` is
772
+ equivalent to:
773
 
774
  ``` cpp
775
  noexcept(x.swap(y))
776
  ```
777
 
778
+ *Effects:* As if by `x.swap(y)`.
779