From Jason Turner

[tuple]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpqrjmbwc9/{from.md → to.md} +283 -302
tmp/tmpqrjmbwc9/{from.md → to.md} RENAMED
@@ -1,30 +1,32 @@
1
  ## Tuples <a id="tuple">[[tuple]]</a>
2
 
3
  ### In general <a id="tuple.general">[[tuple.general]]</a>
4
 
5
- This subclause describes the tuple library that provides a tuple type as
6
- the class template `tuple` that can be instantiated with any number of
7
- arguments. Each template argument specifies the type of an element in
8
- the `tuple`. Consequently, tuples are heterogeneous, fixed-size
9
- collections of values. An instantiation of `tuple` with two arguments is
10
- similar to an instantiation of `pair` with the same two arguments. See 
11
- [[pairs]].
12
 
13
  ### Header `<tuple>` synopsis <a id="tuple.syn">[[tuple.syn]]</a>
14
 
15
  ``` cpp
 
 
16
  namespace std {
17
  // [tuple.tuple], class template tuple
18
  template<class... Types>
19
  class tuple;
20
 
21
  // [tuple.creation], tuple creation functions
22
  inline constexpr unspecified ignore;
23
 
24
  template<class... TTypes>
25
- constexpr tuple<VTypes...> make_tuple(TTypes&&...);
26
 
27
  template<class... TTypes>
28
  constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept;
29
 
30
  template<class... TTypes>
@@ -39,24 +41,20 @@ namespace std {
39
 
40
  template<class T, class Tuple>
41
  constexpr T make_from_tuple(Tuple&& t);
42
 
43
  // [tuple.helper], tuple helper classes
44
- template <class T> class tuple_size; // not defined
45
- template <class T> class tuple_size<const T>;
46
- template <class T> class tuple_size<volatile T>;
47
- template <class T> class tuple_size<const volatile T>;
48
 
49
- template <class... Types> class tuple_size<tuple<Types...>>;
50
 
51
- template <size_t I, class T> class tuple_element; // not defined
52
- template <size_t I, class T> class tuple_element<I, const T>;
53
- template <size_t I, class T> class tuple_element<I, volatile T>;
54
- template <size_t I, class T> class tuple_element<I, const volatile T>;
55
 
56
  template<size_t I, class... Types>
57
- class tuple_element<I, tuple<Types...>>;
58
 
59
  template<size_t I, class T>
60
  using tuple_element_t = typename tuple_element<I, T>::type;
61
 
62
  // [tuple.elem], element access
@@ -79,27 +77,20 @@ namespace std {
79
 
80
  // [tuple.rel], relational operators
81
  template<class... TTypes, class... UTypes>
82
  constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&);
83
  template<class... TTypes, class... UTypes>
84
- constexpr bool operator<(const tuple<TTypes...>&, const tuple<UTypes...>&);
85
- template<class... TTypes, class... UTypes>
86
- constexpr bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&);
87
- template<class... TTypes, class... UTypes>
88
- constexpr bool operator>(const tuple<TTypes...>&, const tuple<UTypes...>&);
89
- template<class... TTypes, class... UTypes>
90
- constexpr bool operator<=(const tuple<TTypes...>&, const tuple<UTypes...>&);
91
- template<class... TTypes, class... UTypes>
92
- constexpr bool operator>=(const tuple<TTypes...>&, const tuple<UTypes...>&);
93
 
94
  // [tuple.traits], allocator-related traits
95
  template<class... Types, class Alloc>
96
  struct uses_allocator<tuple<Types...>, Alloc>;
97
 
98
  // [tuple.special], specialized algorithms
99
  template<class... Types>
100
- void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
101
 
102
  // [tuple.helper], tuple helper classes
103
  template<class T>
104
  inline constexpr size_t tuple_size_v = tuple_size<T>::value;
105
  }
@@ -111,64 +102,71 @@ namespace std {
111
  namespace std {
112
  template<class... Types>
113
  class tuple {
114
  public:
115
  // [tuple.cnstr], tuple construction
116
- \EXPLICIT constexpr tuple();
117
- \EXPLICIT constexpr tuple(const Types&...); // only if sizeof...(Types) >= 1
118
  template<class... UTypes>
119
- \EXPLICIT constexpr tuple(UTypes&&...); // only if sizeof...(Types) >= 1
120
 
121
  tuple(const tuple&) = default;
122
  tuple(tuple&&) = default;
123
 
124
  template<class... UTypes>
125
- \EXPLICIT constexpr tuple(const tuple<UTypes...>&);
126
  template<class... UTypes>
127
- \EXPLICIT constexpr tuple(tuple<UTypes...>&&);
128
 
129
  template<class U1, class U2>
130
- \EXPLICIT constexpr tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2
131
  template<class U1, class U2>
132
- \EXPLICIT constexpr tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2
133
 
134
  // allocator-extended constructors
135
  template<class Alloc>
 
136
  tuple(allocator_arg_t, const Alloc& a);
137
  template<class Alloc>
138
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const Types&...);
 
139
  template<class Alloc, class... UTypes>
140
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
 
141
  template<class Alloc>
142
- tuple(allocator_arg_t, const Alloc& a, const tuple&);
143
  template<class Alloc>
144
- tuple(allocator_arg_t, const Alloc& a, tuple&&);
145
  template<class Alloc, class... UTypes>
146
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
 
147
  template<class Alloc, class... UTypes>
148
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
 
149
  template<class Alloc, class U1, class U2>
150
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
 
151
  template<class Alloc, class U1, class U2>
152
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
 
153
 
154
  // [tuple.assign], tuple assignment
155
- tuple& operator=(const tuple&);
156
- tuple& operator=(tuple&&) noexcept(see below);
157
 
158
  template<class... UTypes>
159
- tuple& operator=(const tuple<UTypes...>&);
160
  template<class... UTypes>
161
- tuple& operator=(tuple<UTypes...>&&);
162
 
163
  template<class U1, class U2>
164
- tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2
165
  template<class U1, class U2>
166
- tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2
167
 
168
  // [tuple.swap], tuple swap
169
- void swap(tuple&) noexcept(see below);
170
  };
171
 
172
  template<class... UTypes>
173
  tuple(UTypes...) -> tuple<UTypes...>;
174
  template<class T1, class T2>
@@ -182,186 +180,211 @@ namespace std {
182
  }
183
  ```
184
 
185
  #### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
186
 
 
 
 
 
 
187
  For each `tuple` constructor, an exception is thrown only if the
188
  construction of one of the types in `Types` throws an exception.
189
 
190
- The defaulted move and copy constructor, respectively, of `tuple` shall
191
- be a constexpr function if and only if all required element-wise
192
- initializations for copy and move, respectively, would satisfy the
193
  requirements for a constexpr function. The defaulted move and copy
194
- constructor of `tuple<>` shall be constexpr functions.
195
 
196
- The destructor of tuple shall be a trivial destructor if
197
- `(is_trivially_destructible_v<Types> && ...)` is `true`.
198
-
199
- In the constructor descriptions that follow, let i be in the range
200
- \[`0`, `sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`,
201
- and `Uᵢ` be the iᵗʰ type in a template parameter pack named `UTypes`,
202
- where indexing is zero-based.
203
 
204
  ``` cpp
205
- \EXPLICIT constexpr tuple();
206
  ```
207
 
 
 
208
  *Effects:* Value-initializes each element.
209
 
210
- *Remarks:* This constructor shall not participate in overload resolution
211
- unless `is_default_constructible_v<``Tᵢ``>` is `true` for all i.
 
212
 
213
- [*Note 1*: This behavior can be implemented by a constructor template
214
- with default template arguments. — *end note*]
215
-
216
- The constructor is explicit if and only if `Tᵢ` is not implicitly
217
- default-constructible for at least one i.
218
-
219
- [*Note 2*: This behavior can be implemented with a trait that checks
220
  whether a `const ``Tᵢ``&` can be initialized with `{}`. — *end note*]
221
 
222
  ``` cpp
223
- \EXPLICIT constexpr tuple(const Types&...);
224
  ```
225
 
 
 
 
226
  *Effects:* Initializes each element with the value of the corresponding
227
  parameter.
228
 
229
- *Remarks:* This constructor shall not participate in overload resolution
230
- unless `sizeof...(Types) >= 1` and `is_copy_constructible_v<``Tᵢ``>` is
231
- `true` for all i. The constructor is explicit if and only if
232
- `is_convertible_v<const ``Tᵢ``&, ``Tᵢ``>` is `false` for at least one i.
233
 
234
  ``` cpp
235
- template <class... UTypes> \EXPLICIT constexpr tuple(UTypes&&... u);
236
  ```
237
 
 
 
 
 
 
 
 
 
238
  *Effects:* Initializes the elements in the tuple with the corresponding
239
  value in `std::forward<UTypes>(u)`.
240
 
241
- *Remarks:* This constructor shall not participate in overload resolution
242
- unless `sizeof...(Types)` `==` `sizeof...(UTypes)` and
243
- `sizeof...(Types) >= 1` and `is_constructible_v<``Tᵢ``, ``Uᵢ``&&>` is
244
- `true` for all i. The constructor is explicit if and only if
245
- `is_convertible_v<``Uᵢ``&&, ``Tᵢ``>` is `false` for at least one i.
246
 
247
  ``` cpp
248
  tuple(const tuple& u) = default;
249
  ```
250
 
251
- *Requires:* `is_copy_constructible_v<``Tᵢ``>` is `true` for all i.
252
 
253
  *Effects:* Initializes each element of `*this` with the corresponding
254
  element of `u`.
255
 
256
  ``` cpp
257
  tuple(tuple&& u) = default;
258
  ```
259
 
260
- *Requires:* `is_move_constructible_v<``Tᵢ``>` is `true` for all i.
261
 
262
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
263
  `std::forward<``Tᵢ``>(get<`i`>(u))`.
264
 
265
  ``` cpp
266
- template <class... UTypes> \EXPLICIT constexpr tuple(const tuple<UTypes...>& u);
267
  ```
268
 
269
- *Effects:* Initializes each element of `*this` with the corresponding
270
- element of `u`.
271
 
272
- *Remarks:* This constructor shall not participate in overload resolution
273
- unless
274
-
275
- - `sizeof...(Types)` `==` `sizeof...(UTypes)` and
276
  - `is_constructible_v<``Tᵢ``, const ``Uᵢ``&>` is `true` for all i, and
277
- - `sizeof...(Types) != 1`, or (when `Types...` expands to `T` and
278
- `UTypes...` expands to `U`)
279
- `!is_convertible_v<const tuple<U>&, T> && !is_constructible_v<T, const tuple<U>&>&& !is_same_v<T, U>`
280
- is `true`.
 
281
 
282
- The constructor is explicit if and only if
283
- `is_convertible_v<const ``Uᵢ``&, ``Tᵢ``>` is `false` for at least one i.
 
 
 
 
 
 
284
 
285
  ``` cpp
286
- template <class... UTypes> \EXPLICIT constexpr tuple(tuple<UTypes...>&& u);
287
  ```
288
 
 
 
 
 
 
 
 
 
 
289
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
290
  `std::forward<``Uᵢ``>(get<`i`>(u))`.
291
 
292
- *Remarks:* This constructor shall not participate in overload resolution
293
- unless
294
 
295
- - `sizeof...(Types)` `==` `sizeof...(UTypes)`, and
296
- - `is_constructible_v<``Tᵢ``, ``Uᵢ``&&>` is `true` for all i, and
297
- - `sizeof...(Types) != 1`, or (when `Types...` expands to `T` and
298
- `UTypes...` expands to `U`)
299
- `!is_convertible_v<tuple<U>, T> && !is_constructible_v<T, tuple<U>> &&!is_same_v<T, U>`
300
- is `true`.
301
-
302
- The constructor is explicit if and only if
303
- `is_convertible_v<``Uᵢ``&&, ``Tᵢ``>` is `false` for at least one i.
304
 
305
  ``` cpp
306
- template <class U1, class U2> \EXPLICIT constexpr tuple(const pair<U1, U2>& u);
307
  ```
308
 
 
 
 
 
 
 
309
  *Effects:* Initializes the first element with `u.first` and the second
310
  element with `u.second`.
311
 
312
- *Remarks:* This constructor shall not participate in overload resolution
313
- unless `sizeof...(Types) == 2`, `is_constructible_v<``T₀``, const U1&>`
314
- is `true` and `is_constructible_v<``T₁``, const U2&>` is `true`.
315
 
316
- The constructor is explicit if and only if
317
- `is_convertible_v<const U1&, ``T₀``>` is `false` or
318
- `is_convertible_v<const U2&, ``T₁``>` is `false`.
319
 
320
  ``` cpp
321
- template <class U1, class U2> \EXPLICIT constexpr tuple(pair<U1, U2>&& u);
322
  ```
323
 
 
 
 
 
 
 
324
  *Effects:* Initializes the first element with
325
  `std::forward<U1>(u.first)` and the second element with
326
  `std::forward<U2>(u.second)`.
327
 
328
- *Remarks:* This constructor shall not participate in overload resolution
329
- unless `sizeof...(Types) == 2`, `is_constructible_v<``T₀``, U1&&>` is
330
- `true` and `is_constructible_v<``T₁``, U2&&>` is `true`.
331
 
332
- The constructor is explicit if and only if
333
- `is_convertible_v<U1&&, ``T₀``>` is `false` or
334
- `is_convertible_v<U2&&, ``T₁``>` is `false`.
335
 
336
  ``` cpp
337
  template<class Alloc>
 
338
  tuple(allocator_arg_t, const Alloc& a);
339
  template<class Alloc>
340
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const Types&...);
 
341
  template<class Alloc, class... UTypes>
342
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
 
343
  template<class Alloc>
344
- tuple(allocator_arg_t, const Alloc& a, const tuple&);
345
  template<class Alloc>
346
- tuple(allocator_arg_t, const Alloc& a, tuple&&);
347
  template<class Alloc, class... UTypes>
348
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
 
349
  template<class Alloc, class... UTypes>
350
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
 
351
  template<class Alloc, class U1, class U2>
352
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
 
353
  template<class Alloc, class U1, class U2>
354
- \EXPLICIT tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
 
355
  ```
356
 
357
- *Requires:* `Alloc` shall meet the requirements for an
358
- `Allocator` ([[allocator.requirements]]).
359
 
360
  *Effects:* Equivalent to the preceding constructors except that each
361
  element is constructed with uses-allocator
362
- construction ([[allocator.uses.construction]]).
363
 
364
  #### Assignment <a id="tuple.assign">[[tuple.assign]]</a>
365
 
366
  For each `tuple` assignment operator, an exception is thrown only if the
367
  assignment of one of the types in `Types` throws an exception. In the
@@ -369,31 +392,30 @@ function descriptions that follow, let i be in the range \[`0`,
369
  `sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`, and `Uᵢ`
370
  be the iᵗʰ type in a template parameter pack named `UTypes`, where
371
  indexing is zero-based.
372
 
373
  ``` cpp
374
- tuple& operator=(const tuple& u);
375
  ```
376
 
377
  *Effects:* Assigns each element of `u` to the corresponding element of
378
  `*this`.
379
 
380
- *Remarks:* This operator shall be defined as deleted unless
381
  `is_copy_assignable_v<``Tᵢ``>` is `true` for all i.
382
 
383
  *Returns:* `*this`.
384
 
385
  ``` cpp
386
- tuple& operator=(tuple&& u) noexcept(see below);
387
  ```
388
 
 
 
389
  *Effects:* For all i, assigns `std::forward<``Tᵢ``>(get<`i`>(u))` to
390
  `get<`i`>(*this)`.
391
 
392
- *Remarks:* This operator shall be defined as deleted unless
393
- `is_move_assignable_v<``Tᵢ``>` is `true` for all i.
394
-
395
  *Remarks:* The expression inside `noexcept` is equivalent to the logical
396
  <span class="smallcaps">and</span> of the following expressions:
397
 
398
  ``` cpp
399
  is_nothrow_move_assignable_v<Tᵢ>
@@ -402,74 +424,76 @@ is_nothrow_move_assignable_v<Tᵢ>
402
  where Tᵢ is the iᵗʰ type in `Types`.
403
 
404
  *Returns:* `*this`.
405
 
406
  ``` cpp
407
- template <class... UTypes> tuple& operator=(const tuple<UTypes...>& u);
408
  ```
409
 
 
 
 
 
 
410
  *Effects:* Assigns each element of `u` to the corresponding element of
411
  `*this`.
412
 
413
- *Remarks:* This operator shall not participate in overload resolution
414
- unless `sizeof...(Types) == sizeof...(UTypes)` and
415
- `is_assignable_v<``Tᵢ``&, const ``Uᵢ``&>` is `true` for all i.
416
-
417
  *Returns:* `*this`.
418
 
419
  ``` cpp
420
- template <class... UTypes> tuple& operator=(tuple<UTypes...>&& u);
421
  ```
422
 
 
 
 
 
 
423
  *Effects:* For all i, assigns `std::forward<``Uᵢ``>(get<`i`>(u))` to
424
  `get<`i`>(*this)`.
425
 
426
- *Remarks:* This operator shall not participate in overload resolution
427
- unless `is_assignable_v<``Tᵢ``&, ``Uᵢ``&&> == true` for all i and
428
- `sizeof...(Types) == sizeof...(UTypes)`.
429
-
430
  *Returns:* `*this`.
431
 
432
  ``` cpp
433
- template <class U1, class U2> tuple& operator=(const pair<U1, U2>& u);
434
  ```
435
 
 
 
 
 
 
 
436
  *Effects:* Assigns `u.first` to the first element of `*this` and
437
  `u.second` to the second element of `*this`.
438
 
439
- *Remarks:* This operator shall not participate in overload resolution
440
- unless `sizeof...(Types) == 2` and `is_assignable_v<``T₀``&, const U1&>`
441
- is `true` for the first type `T₀` in `Types` and
442
- `is_assignable_v<``T₁``&, const U2&>` is `true` for the second type `T₁`
443
- in `Types`.
444
-
445
  *Returns:* `*this`.
446
 
447
  ``` cpp
448
- template <class U1, class U2> tuple& operator=(pair<U1, U2>&& u);
449
  ```
450
 
 
 
 
 
 
 
451
  *Effects:* Assigns `std::forward<U1>(u.first)` to the first element of
452
  `*this` and
453
  `std::forward<U2>(u.second)` to the second element of `*this`.
454
 
455
- *Remarks:* This operator shall not participate in overload resolution
456
- unless `sizeof...(Types) == 2` and `is_assignable_v<``T₀``&, U1&&>` is
457
- `true` for the first type `T₀` in `Types` and
458
- `is_assignable_v<``T₁``&, U2&&>` is `true` for the second type `T₁` in
459
- `Types`.
460
-
461
  *Returns:* `*this`.
462
 
463
  #### `swap` <a id="tuple.swap">[[tuple.swap]]</a>
464
 
465
  ``` cpp
466
- void swap(tuple& rhs) noexcept(see below);
467
  ```
468
 
469
- *Requires:* Each element in `*this` shall be swappable
470
- with ([[swappable.requirements]]) the corresponding element in `rhs`.
471
 
472
  *Effects:* Calls `swap` for each element in `*this` and its
473
  corresponding element in `rhs`.
474
 
475
  *Remarks:* The expression inside `noexcept` is equivalent to the logical
@@ -482,27 +506,23 @@ is_nothrow_swappable_v<Tᵢ>
482
  where Tᵢ is the iᵗʰ type in `Types`.
483
 
484
  *Throws:* Nothing unless one of the element-wise `swap` calls throws an
485
  exception.
486
 
487
- #### Tuple creation functions <a id="tuple.creation">[[tuple.creation]]</a>
488
 
489
- In the function descriptions that follow, the members of a parameter
490
- pack `XTypes` are denoted by `X`ᵢ for i in \[`0`,
491
  `sizeof...(`*X*`Types)`) in order, where indexing is zero-based.
492
 
493
  ``` cpp
494
  template<class... TTypes>
495
- constexpr tuple<VTypes...> make_tuple(TTypes&&... t);
496
  ```
497
 
498
- The pack `VTypes` is defined as follows. Let `U`ᵢ be `decay_t<T`ᵢ`>` for
499
- each `T`ᵢ in `TTypes`. If `U`ᵢ is a specialization of
500
- `reference_wrapper`, then `V`ᵢ in `VTypes` is `U`ᵢ`::type&`, otherwise
501
- `V`ᵢ is `U`ᵢ.
502
-
503
- *Returns:* `tuple<VTypes...>(std::forward<TTypes>(t)...)`.
504
 
505
  [*Example 1*:
506
 
507
  ``` cpp
508
  int i; float j;
@@ -518,14 +538,14 @@ template<class... TTypes>
518
  constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&... t) noexcept;
519
  ```
520
 
521
  *Effects:* Constructs a tuple of references to the arguments in `t`
522
  suitable for forwarding as arguments to a function. Because the result
523
- may contain references to temporary variables, a program shall ensure
524
- that the return value of this function does not outlive any of its
525
- arguments (e.g., the program should typically not store the result in a
526
- named variable).
527
 
528
  *Returns:* `tuple<TTypes&&...>(std::forward<TTypes>(t)...)`.
529
 
530
  ``` cpp
531
  template<class... TTypes>
@@ -556,22 +576,22 @@ template <class... Tuples>
556
 
557
  In the following paragraphs, let `Tᵢ` be the iᵗʰ type in `Tuples`, `Uᵢ`
558
  be `remove_reference_t<T`ᵢ`>`, and `tpᵢ` be the iᵗʰ parameter in the
559
  function parameter pack `tpls`, where all indexing is zero-based.
560
 
561
- *Requires:* For all i, `Uᵢ` shall be the type cvᵢ `tuple<``Argsᵢ``...>`,
562
  where cvᵢ is the (possibly empty) iᵗʰ *cv-qualifier-seq* and `Argsᵢ` is
563
- the parameter pack representing the element types in `Uᵢ`. Let `A_ik` be
564
- the kᵗʰ type in `Argsᵢ`. For all `A_ik` the following requirements shall
565
- be satisfied:
566
 
567
  - If `Tᵢ` is deduced as an lvalue reference type, then
568
  `is_constructible_v<``A_ik``, `cvᵢ `A_ik``&> == true`, otherwise
569
  - `is_constructible_v<``A_ik``, `cvᵢ `A_ik``&&> == true`.
570
 
571
- *Remarks:* The types in `CTypes` shall be equal to the ordered sequence
572
- of the extended types `Args₀``..., ``Args₁``..., `…`, ``Args_n-1``...`,
573
  where n is equal to `sizeof...(Tuples)`. Let `eᵢ``...` be the iᵗʰ
574
  ordered sequence of tuple elements of the resulting `tuple` object
575
  corresponding to the type sequence `Argsᵢ`.
576
 
577
  *Returns:* A `tuple` object constructed by initializing the kᵢᵗʰ type
@@ -582,35 +602,35 @@ get<kᵢ>(std::forward<$T_i$>($tp_i$))
582
  ```
583
 
584
  for each valid kᵢ and each group `eᵢ` in order.
585
 
586
  [*Note 1*: An implementation may support additional types in the
587
- parameter pack `Tuples` that support the `tuple`-like protocol, such as
588
- `pair` and `array`. — *end note*]
589
 
590
- #### Calling a function with a `tuple` of arguments <a id="tuple.apply">[[tuple.apply]]</a>
591
 
592
  ``` cpp
593
  template<class F, class Tuple>
594
  constexpr decltype(auto) apply(F&& f, Tuple&& t);
595
  ```
596
 
597
  *Effects:* Given the exposition-only function:
598
 
599
  ``` cpp
600
  template<class F, class Tuple, size_t... I>
601
- constexpr decltype(auto)
602
- apply_impl(F&& f, Tuple&& t, index_sequence<I...>) { // exposition only
603
- return INVOKE(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
604
  }
605
  ```
606
 
607
  Equivalent to:
608
 
609
  ``` cpp
610
- return apply_impl(std::forward<F>(f), std::forward<Tuple>(t),
611
- make_index_sequence<tuple_size_v<decay_t<Tuple>>>{});
612
  ```
613
 
614
  ``` cpp
615
  template<class T, class Tuple>
616
  constexpr T make_from_tuple(Tuple&& t);
@@ -618,107 +638,98 @@ template <class T, class Tuple>
618
 
619
  *Effects:* Given the exposition-only function:
620
 
621
  ``` cpp
622
  template<class T, class Tuple, size_t... I>
623
- constexpr T make_from_tuple_impl(Tuple&& t, index_sequence<I...>) { // exposition only
624
  return T(get<I>(std::forward<Tuple>(t))...);
625
  }
626
  ```
627
 
628
  Equivalent to:
629
 
630
  ``` cpp
631
- return make_from_tuple_impl<T>(forward<Tuple>(t),
632
- make_index_sequence<tuple_size_v<decay_t<Tuple>>>{});
 
633
  ```
634
 
635
  [*Note 1*: The type of `T` must be supplied as an explicit template
636
  parameter, as it cannot be deduced from the argument
637
  list. — *end note*]
638
 
639
- #### Tuple helper classes <a id="tuple.helper">[[tuple.helper]]</a>
640
 
641
  ``` cpp
642
  template<class T> struct tuple_size;
643
  ```
644
 
645
- *Remarks:* All specializations of `tuple_size` shall meet the
646
- `UnaryTypeTrait` requirements ([[meta.rqmts]]) with a base
647
- characteristic of `integral_constant<size_t, N>` for some `N`.
648
 
649
  ``` cpp
650
  template<class... Types>
651
- class tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
652
  ```
653
 
654
  ``` cpp
655
  template<size_t I, class... Types>
656
- class tuple_element<I, tuple<Types...>> {
657
- public:
658
  using type = TI;
659
  };
660
  ```
661
 
662
- *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
663
- out of bounds.
664
 
665
- *Type:* `TI` is the type of the `I`th element of `Types`, where indexing
666
  is zero-based.
667
 
668
  ``` cpp
669
- template <class T> class tuple_size<const T>;
670
- template <class T> class tuple_size<volatile T>;
671
- template <class T> class tuple_size<const volatile T>;
672
  ```
673
 
674
- Let *`TS`* denote `tuple_size<T>` of the cv-unqualified type `T`. If the
675
- expression *`TS`*`::value` is well-formed when treated as an unevaluated
676
- operand, then each of the three templates shall meet the
677
- `UnaryTypeTrait` requirements ([[meta.rqmts]]) with a base
678
  characteristic of
679
 
680
  ``` cpp
681
  integral_constant<size_t, TS::value>
682
  ```
683
 
684
- Otherwise, they shall have no member `value`.
685
 
686
- Access checking is performed as if in a context unrelated to *`TS`* and
687
  `T`. Only the validity of the immediate context of the expression is
688
  considered.
689
 
690
  [*Note 1*: The compilation of the expression can result in side effects
691
  such as the instantiation of class template specializations and function
692
  template specializations, the generation of implicitly-defined
693
  functions, and so on. Such side effects are not in the “immediate
694
  context” and can result in the program being ill-formed. — *end note*]
695
 
696
  In addition to being available via inclusion of the `<tuple>` header,
697
- the three templates are available when either of the headers `<array>`
698
  or `<utility>` are included.
699
 
700
  ``` cpp
701
- template <size_t I, class T> class tuple_element<I, const T>;
702
- template <size_t I, class T> class tuple_element<I, volatile T>;
703
- template <size_t I, class T> class tuple_element<I, const volatile T>;
704
  ```
705
 
706
- Let *`TE`* denote `tuple_element_t<I, T>` of the cv-unqualified type
707
- `T`. Then each of the three templates shall meet the
708
- `TransformationTrait` requirements ([[meta.rqmts]]) with a member
709
- typedef `type` that names the following type:
710
-
711
- - for the first specialization, `add_const_t<`*`TE`*`>`,
712
- - for the second specialization, `add_volatile_t<`*`TE`*`>`, and
713
- - for the third specialization, `add_cv_t<`*`TE`*`>`.
714
 
715
  In addition to being available via inclusion of the `<tuple>` header,
716
- the three templates are available when either of the headers `<array>`
717
  or `<utility>` are included.
718
 
719
- #### Element access <a id="tuple.elem">[[tuple.elem]]</a>
720
 
721
  ``` cpp
722
  template<size_t I, class... Types>
723
  constexpr tuple_element_t<I, tuple<Types...>>&
724
  get(tuple<Types...>& t) noexcept;
@@ -730,25 +741,24 @@ template <size_t I, class... Types>
730
  get(const tuple<Types...>& t) noexcept; // Note B
731
  template<size_t I, class... Types>
732
  constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
733
  ```
734
 
735
- *Requires:* `I < sizeof...(Types)`. The program is ill-formed if `I` is
736
- out of bounds.
737
 
738
- *Returns:* A reference to the `I`th element of `t`, where indexing is
739
  zero-based.
740
 
741
- [*Note 1*: \[Note A\]If a `T` in `Types` is some reference type `X&`,
742
- the return type is `X&`, not `X&&`. However, if the element type is a
743
- non-reference type `T`, the return type is `T&&`. — *end note*]
744
 
745
- [*Note 2*: \[Note B\]Constness is shallow. If a `T` in `Types` is some
746
- reference type `X&`, the return type is `X&`, not `const X&`. However,
747
- if the element type is a non-reference type `T`, the return type is
748
- `const T&`. This is consistent with how constness is defined to work for
749
- member variables of reference type. — *end note*]
750
 
751
  ``` cpp
752
  template<class T, class... Types>
753
  constexpr T& get(tuple<Types...>& t) noexcept;
754
  template<class T, class... Types>
@@ -757,42 +767,41 @@ template <class T, class... Types>
757
  constexpr const T& get(const tuple<Types...>& t) noexcept;
758
  template<class T, class... Types>
759
  constexpr const T&& get(const tuple<Types...>&& t) noexcept;
760
  ```
761
 
762
- *Requires:* The type `T` occurs exactly once in `Types...`. Otherwise,
763
- the program is ill-formed.
764
 
765
  *Returns:* A reference to the element of `t` corresponding to the type
766
- `T` in `Types...`.
767
 
768
  [*Example 1*:
769
 
770
  ``` cpp
771
  const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
772
- const int& i1 = get<int>(t); // OK. Not ambiguous. i1 == 1
773
- const int& i2 = get<const int>(t); // OK. Not ambiguous. i2 == 2
774
- const double& d = get<double>(t); // ERROR. ill-formed
775
  ```
776
 
777
  — *end example*]
778
 
779
  [*Note 1*: The reason `get` is a non-member function is that if this
780
  functionality had been provided as a member function, code where the
781
  type depended on a template parameter would have required using the
782
  `template` keyword. — *end note*]
783
 
784
- #### Relational operators <a id="tuple.rel">[[tuple.rel]]</a>
785
 
786
  ``` cpp
787
  template<class... TTypes, class... UTypes>
788
  constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
789
  ```
790
 
791
- *Requires:* For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`,
792
  `get<i>(t) == get<i>(u)` is a valid expression returning a type that is
793
- convertible to `bool`. `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
794
 
795
  *Returns:* `true` if `get<i>(t) == get<i>(u)` for all `i`, otherwise
796
  `false`. For any two zero-length tuples `e` and `f`, `e == f` returns
797
  `true`.
798
 
@@ -800,85 +809,57 @@ convertible to `bool`. `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
800
  zeroth index upwards. No comparisons or element accesses are performed
801
  after the first equality comparison that evaluates to `false`.
802
 
803
  ``` cpp
804
  template<class... TTypes, class... UTypes>
805
- constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
 
806
  ```
807
 
808
- *Requires:* For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`,
809
- both `get<i>(t) < get<i>(u)` and `get<i>(u) < get<i>(t)` are valid
810
- expressions returning types that are convertible to `bool`.
811
- `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
812
-
813
- *Returns:* The result of a lexicographical comparison between `t` and
814
- `u`. The result is defined as:
815
- `(bool)(get<0>(t) < get<0>(u)) || (!(bool)(get<0>(u) < get<0>(t)) && t`ₜₐᵢₗ` < u`ₜₐᵢₗ`)`,
816
- where `r`ₜₐᵢₗ for some tuple `r` is a tuple containing all but the first
817
- element of `r`. For any two zero-length tuples `e` and `f`, `e < f`
818
- returns `false`.
819
-
820
- ``` cpp
821
- template<class... TTypes, class... UTypes>
822
- constexpr bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
823
- ```
824
-
825
- *Returns:* `!(t == u)`.
826
-
827
- ``` cpp
828
- template<class... TTypes, class... UTypes>
829
- constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
830
- ```
831
-
832
- *Returns:* `u < t`.
833
-
834
- ``` cpp
835
- template<class... TTypes, class... UTypes>
836
- constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
837
- ```
838
-
839
- *Returns:* `!(u < t)`.
840
 
841
  ``` cpp
842
- template<class... TTypes, class... UTypes>
843
- constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
844
  ```
845
 
846
- *Returns:* `!(t < u)`.
 
847
 
848
- [*Note 1*: The above definitions for comparison functions do not
849
- require `tₜₐᵢₗ` (or `uₜₐᵢₗ`) to be constructed. It may not even be
850
- possible, as `t` and `u` are not required to be copy constructible.
851
- Also, all comparison functions are short circuited; they do not perform
852
- element accesses beyond what is required to determine the result of the
853
- comparison. — *end note*]
854
 
855
- #### Tuple traits <a id="tuple.traits">[[tuple.traits]]</a>
856
 
857
  ``` cpp
858
  template<class... Types, class Alloc>
859
  struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
860
  ```
861
 
862
- *Requires:* `Alloc` shall be an
863
- `Allocator` ([[allocator.requirements]]).
864
 
865
  [*Note 1*: Specialization of this trait informs other library
866
  components that `tuple` can be constructed with an allocator, even
867
  though it does not have a nested `allocator_type`. — *end note*]
868
 
869
- #### Tuple specialized algorithms <a id="tuple.special">[[tuple.special]]</a>
870
 
871
  ``` cpp
872
  template<class... Types>
873
- void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
874
  ```
875
 
876
- *Remarks:* This function shall not participate in overload resolution
877
- unless `is_swappable_v<``Tᵢ``>` is `true` for all i, where
878
- 0 ≤ i < `sizeof...(Types)`. The expression inside `noexcept` is
879
- equivalent to:
880
 
881
  ``` cpp
882
  noexcept(x.swap(y))
883
  ```
884
 
 
1
  ## Tuples <a id="tuple">[[tuple]]</a>
2
 
3
  ### In general <a id="tuple.general">[[tuple.general]]</a>
4
 
5
+ Subclause  [[tuple]] describes the tuple library that provides a tuple
6
+ type as the class template `tuple` that can be instantiated with any
7
+ number of arguments. Each template argument specifies the type of an
8
+ element in the `tuple`. Consequently, tuples are heterogeneous,
9
+ fixed-size collections of values. An instantiation of `tuple` with two
10
+ arguments is similar to an instantiation of `pair` with the same two
11
+ arguments. See  [[pairs]].
12
 
13
  ### Header `<tuple>` synopsis <a id="tuple.syn">[[tuple.syn]]</a>
14
 
15
  ``` cpp
16
+ #include <compare> // see [compare.syn]
17
+
18
  namespace std {
19
  // [tuple.tuple], class template tuple
20
  template<class... Types>
21
  class tuple;
22
 
23
  // [tuple.creation], tuple creation functions
24
  inline constexpr unspecified ignore;
25
 
26
  template<class... TTypes>
27
+ constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&...);
28
 
29
  template<class... TTypes>
30
  constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept;
31
 
32
  template<class... TTypes>
 
41
 
42
  template<class T, class Tuple>
43
  constexpr T make_from_tuple(Tuple&& t);
44
 
45
  // [tuple.helper], tuple helper classes
46
+ template<class T> struct tuple_size; // not defined
47
+ template<class T> struct tuple_size<const T>;
 
 
48
 
49
+ template<class... Types> struct tuple_size<tuple<Types...>>;
50
 
51
+ template<size_t I, class T> struct tuple_element; // not defined
52
+ template<size_t I, class T> struct tuple_element<I, const T>;
 
 
53
 
54
  template<size_t I, class... Types>
55
+ struct tuple_element<I, tuple<Types...>>;
56
 
57
  template<size_t I, class T>
58
  using tuple_element_t = typename tuple_element<I, T>::type;
59
 
60
  // [tuple.elem], element access
 
77
 
78
  // [tuple.rel], relational operators
79
  template<class... TTypes, class... UTypes>
80
  constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&);
81
  template<class... TTypes, class... UTypes>
82
+ constexpr common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...>
83
+ operator<=>(const tuple<TTypes...>&, const tuple<UTypes...>&);
 
 
 
 
 
 
 
84
 
85
  // [tuple.traits], allocator-related traits
86
  template<class... Types, class Alloc>
87
  struct uses_allocator<tuple<Types...>, Alloc>;
88
 
89
  // [tuple.special], specialized algorithms
90
  template<class... Types>
91
+ constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
92
 
93
  // [tuple.helper], tuple helper classes
94
  template<class T>
95
  inline constexpr size_t tuple_size_v = tuple_size<T>::value;
96
  }
 
102
  namespace std {
103
  template<class... Types>
104
  class tuple {
105
  public:
106
  // [tuple.cnstr], tuple construction
107
+ constexpr explicit(see below) tuple();
108
+ constexpr explicit(see below) tuple(const Types&...); // only if sizeof...(Types) >= 1
109
  template<class... UTypes>
110
+ constexpr explicit(see below) tuple(UTypes&&...); // only if sizeof...(Types) >= 1
111
 
112
  tuple(const tuple&) = default;
113
  tuple(tuple&&) = default;
114
 
115
  template<class... UTypes>
116
+ constexpr explicit(see below) tuple(const tuple<UTypes...>&);
117
  template<class... UTypes>
118
+ constexpr explicit(see below) tuple(tuple<UTypes...>&&);
119
 
120
  template<class U1, class U2>
121
+ constexpr explicit(see below) tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2
122
  template<class U1, class U2>
123
+ constexpr explicit(see below) tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2
124
 
125
  // allocator-extended constructors
126
  template<class Alloc>
127
+ constexpr explicit(see below)
128
  tuple(allocator_arg_t, const Alloc& a);
129
  template<class Alloc>
130
+ constexpr explicit(see below)
131
+ tuple(allocator_arg_t, const Alloc& a, const Types&...);
132
  template<class Alloc, class... UTypes>
133
+ constexpr explicit(see below)
134
+ tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
135
  template<class Alloc>
136
+ constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
137
  template<class Alloc>
138
+ constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
139
  template<class Alloc, class... UTypes>
140
+ constexpr explicit(see below)
141
+ tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
142
  template<class Alloc, class... UTypes>
143
+ constexpr explicit(see below)
144
+ tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
145
  template<class Alloc, class U1, class U2>
146
+ constexpr explicit(see below)
147
+ tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
148
  template<class Alloc, class U1, class U2>
149
+ constexpr explicit(see below)
150
+ tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
151
 
152
  // [tuple.assign], tuple assignment
153
+ constexpr tuple& operator=(const tuple&);
154
+ constexpr tuple& operator=(tuple&&) noexcept(see below);
155
 
156
  template<class... UTypes>
157
+ constexpr tuple& operator=(const tuple<UTypes...>&);
158
  template<class... UTypes>
159
+ constexpr tuple& operator=(tuple<UTypes...>&&);
160
 
161
  template<class U1, class U2>
162
+ constexpr tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2
163
  template<class U1, class U2>
164
+ constexpr tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2
165
 
166
  // [tuple.swap], tuple swap
167
+ constexpr void swap(tuple&) noexcept(see below);
168
  };
169
 
170
  template<class... UTypes>
171
  tuple(UTypes...) -> tuple<UTypes...>;
172
  template<class T1, class T2>
 
180
  }
181
  ```
182
 
183
  #### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
184
 
185
+ In the descriptions that follow, let i be in the range \[`0`,
186
+ `sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`, and `Uᵢ`
187
+ be the iᵗʰ type in a template parameter pack named `UTypes`, where
188
+ indexing is zero-based.
189
+
190
  For each `tuple` constructor, an exception is thrown only if the
191
  construction of one of the types in `Types` throws an exception.
192
 
193
+ The defaulted move and copy constructor, respectively, of `tuple` is a
194
+ constexpr function if and only if all required element-wise
195
+ initializations for move and copy, respectively, would satisfy the
196
  requirements for a constexpr function. The defaulted move and copy
197
+ constructor of `tuple<>` are constexpr functions.
198
 
199
+ If `is_trivially_destructible_v<Tᵢ>` is `true` for all `Tᵢ`, then the
200
+ destructor of `tuple` is trivial.
 
 
 
 
 
201
 
202
  ``` cpp
203
+ constexpr explicit(see below) tuple();
204
  ```
205
 
206
+ *Constraints:* `is_default_constructible_v<``Tᵢ``>` is `true` for all i.
207
+
208
  *Effects:* Value-initializes each element.
209
 
210
+ *Remarks:* The expression inside `explicit` evaluates to `true` if and
211
+ only if `Tᵢ` is not copy-list-initializable from an empty list for at
212
+ least one i.
213
 
214
+ [*Note 1*: This behavior can be implemented with a trait that checks
 
 
 
 
 
 
215
  whether a `const ``Tᵢ``&` can be initialized with `{}`. — *end note*]
216
 
217
  ``` cpp
218
+ constexpr explicit(see below) tuple(const Types&...);
219
  ```
220
 
221
+ *Constraints:* `sizeof...(Types)` ≥ 1 and
222
+ `is_copy_constructible_v<``Tᵢ``>` is `true` for all i.
223
+
224
  *Effects:* Initializes each element with the value of the corresponding
225
  parameter.
226
 
227
+ *Remarks:* The expression inside `explicit` is equivalent to:
 
 
 
228
 
229
  ``` cpp
230
+ !conjunction_v<is_convertible<const Types&, Types>...>
231
  ```
232
 
233
+ ``` cpp
234
+ template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&... u);
235
+ ```
236
+
237
+ *Constraints:* `sizeof...(Types)` equals `sizeof...(UTypes)` and
238
+ `sizeof...(Types)` ≥ 1 and `is_constructible_v<``Tᵢ``, ``Uᵢ``>` is
239
+ `true` for all i.
240
+
241
  *Effects:* Initializes the elements in the tuple with the corresponding
242
  value in `std::forward<UTypes>(u)`.
243
 
244
+ *Remarks:* The expression inside `explicit` is equivalent to:
245
+
246
+ ``` cpp
247
+ !conjunction_v<is_convertible<UTypes, Types>...>
248
+ ```
249
 
250
  ``` cpp
251
  tuple(const tuple& u) = default;
252
  ```
253
 
254
+ *Mandates:* `is_copy_constructible_v<``Tᵢ``>` is `true` for all i.
255
 
256
  *Effects:* Initializes each element of `*this` with the corresponding
257
  element of `u`.
258
 
259
  ``` cpp
260
  tuple(tuple&& u) = default;
261
  ```
262
 
263
+ *Constraints:* `is_move_constructible_v<``Tᵢ``>` is `true` for all i.
264
 
265
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
266
  `std::forward<``Tᵢ``>(get<`i`>(u))`.
267
 
268
  ``` cpp
269
+ template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u);
270
  ```
271
 
272
+ *Constraints:*
 
273
 
274
+ - `sizeof...(Types)` equals `sizeof...(UTypes)` and
 
 
 
275
  - `is_constructible_v<``Tᵢ``, const ``Uᵢ``&>` is `true` for all i, and
276
+ - either `sizeof...(Types)` is not 1, or (when `Types...` expands to `T`
277
+ and `UTypes...` expands to `U`)
278
+ `is_convertible_v<const tuple<U>&, T>`,
279
+ `is_constructible_v<T, const tuple<U>&>`, and `is_same_v<T, U>` are
280
+ all `false`.
281
 
282
+ *Effects:* Initializes each element of `*this` with the corresponding
283
+ element of `u`.
284
+
285
+ *Remarks:* The expression inside `explicit` is equivalent to:
286
+
287
+ ``` cpp
288
+ !conjunction_v<is_convertible<const UTypes&, Types>...>
289
+ ```
290
 
291
  ``` cpp
292
+ template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u);
293
  ```
294
 
295
+ *Constraints:*
296
+
297
+ - `sizeof...(Types)` equals `sizeof...(UTypes)`, and
298
+ - `is_constructible_v<``Tᵢ``, ``Uᵢ``>` is `true` for all i, and
299
+ - either `sizeof...(Types)` is not 1, or (when `Types...` expands to `T`
300
+ and `UTypes...` expands to `U`) `is_convertible_v<tuple<U>, T>`,
301
+ `is_constructible_v<T, tuple<U>>`, and `is_same_v<T, U>` are all
302
+ `false`.
303
+
304
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
305
  `std::forward<``Uᵢ``>(get<`i`>(u))`.
306
 
307
+ *Remarks:* The expression inside `explicit` is equivalent to:
 
308
 
309
+ ``` cpp
310
+ !conjunction_v<is_convertible<UTypes, Types>...>
311
+ ```
 
 
 
 
 
 
312
 
313
  ``` cpp
314
+ template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>& u);
315
  ```
316
 
317
+ *Constraints:*
318
+
319
+ - `sizeof...(Types)` is 2,
320
+ - `is_constructible_v<``T₀``, const U1&>` is `true`, and
321
+ - `is_constructible_v<``T₁``, const U2&>` is `true`.
322
+
323
  *Effects:* Initializes the first element with `u.first` and the second
324
  element with `u.second`.
325
 
326
+ The expression inside `explicit` is equivalent to:
 
 
327
 
328
+ ``` cpp
329
+ !is_convertible_v<const U1&, $T_0$> || !is_convertible_v<const U2&, $T_1$>
330
+ ```
331
 
332
  ``` cpp
333
+ template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&& u);
334
  ```
335
 
336
+ *Constraints:*
337
+
338
+ - `sizeof...(Types)` is 2,
339
+ - `is_constructible_v<``T₀``, U1>` is `true`, and
340
+ - `is_constructible_v<``T₁``, U2>` is `true`.
341
+
342
  *Effects:* Initializes the first element with
343
  `std::forward<U1>(u.first)` and the second element with
344
  `std::forward<U2>(u.second)`.
345
 
346
+ The expression inside `explicit` is equivalent to:
 
 
347
 
348
+ ``` cpp
349
+ !is_convertible_v<U1, $T_0$> || !is_convertible_v<U2, $T_1$>
350
+ ```
351
 
352
  ``` cpp
353
  template<class Alloc>
354
+ constexpr explicit(see below)
355
  tuple(allocator_arg_t, const Alloc& a);
356
  template<class Alloc>
357
+ constexpr explicit(see below)
358
+ tuple(allocator_arg_t, const Alloc& a, const Types&...);
359
  template<class Alloc, class... UTypes>
360
+ constexpr explicit(see below)
361
+ tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
362
  template<class Alloc>
363
+ constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
364
  template<class Alloc>
365
+ constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
366
  template<class Alloc, class... UTypes>
367
+ constexpr explicit(see below)
368
+ tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
369
  template<class Alloc, class... UTypes>
370
+ constexpr explicit(see below)
371
+ tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
372
  template<class Alloc, class U1, class U2>
373
+ constexpr explicit(see below)
374
+ tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
375
  template<class Alloc, class U1, class U2>
376
+ constexpr explicit(see below)
377
+ tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
378
  ```
379
 
380
+ *Preconditions:* `Alloc` meets the *Cpp17Allocator* requirements
381
+ ([[cpp17.allocator]]).
382
 
383
  *Effects:* Equivalent to the preceding constructors except that each
384
  element is constructed with uses-allocator
385
+ construction [[allocator.uses.construction]].
386
 
387
  #### Assignment <a id="tuple.assign">[[tuple.assign]]</a>
388
 
389
  For each `tuple` assignment operator, an exception is thrown only if the
390
  assignment of one of the types in `Types` throws an exception. In the
 
392
  `sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`, and `Uᵢ`
393
  be the iᵗʰ type in a template parameter pack named `UTypes`, where
394
  indexing is zero-based.
395
 
396
  ``` cpp
397
+ constexpr tuple& operator=(const tuple& u);
398
  ```
399
 
400
  *Effects:* Assigns each element of `u` to the corresponding element of
401
  `*this`.
402
 
403
+ *Remarks:* This operator is defined as deleted unless
404
  `is_copy_assignable_v<``Tᵢ``>` is `true` for all i.
405
 
406
  *Returns:* `*this`.
407
 
408
  ``` cpp
409
+ constexpr tuple& operator=(tuple&& u) noexcept(see below);
410
  ```
411
 
412
+ *Constraints:* `is_move_assignable_v<``Tᵢ``>` is `true` for all i.
413
+
414
  *Effects:* For all i, assigns `std::forward<``Tᵢ``>(get<`i`>(u))` to
415
  `get<`i`>(*this)`.
416
 
 
 
 
417
  *Remarks:* The expression inside `noexcept` is equivalent to the logical
418
  <span class="smallcaps">and</span> of the following expressions:
419
 
420
  ``` cpp
421
  is_nothrow_move_assignable_v<Tᵢ>
 
424
  where Tᵢ is the iᵗʰ type in `Types`.
425
 
426
  *Returns:* `*this`.
427
 
428
  ``` cpp
429
+ template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>& u);
430
  ```
431
 
432
+ *Constraints:*
433
+
434
+ - `sizeof...(Types)` equals `sizeof...(UTypes)` and
435
+ - `is_assignable_v<``Tᵢ``&, const ``Uᵢ``&>` is `true` for all i.
436
+
437
  *Effects:* Assigns each element of `u` to the corresponding element of
438
  `*this`.
439
 
 
 
 
 
440
  *Returns:* `*this`.
441
 
442
  ``` cpp
443
+ template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&& u);
444
  ```
445
 
446
+ *Constraints:*
447
+
448
+ - `sizeof...(Types)` equals `sizeof...(UTypes)` and
449
+ - `is_assignable_v<``Tᵢ``&, ``Uᵢ``>` is `true` for all i.
450
+
451
  *Effects:* For all i, assigns `std::forward<``Uᵢ``>(get<`i`>(u))` to
452
  `get<`i`>(*this)`.
453
 
 
 
 
 
454
  *Returns:* `*this`.
455
 
456
  ``` cpp
457
+ template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>& u);
458
  ```
459
 
460
+ *Constraints:*
461
+
462
+ - `sizeof...(Types)` is 2 and
463
+ - `is_assignable_v<``T₀``&, const U1&>` is `true`, and
464
+ - `is_assignable_v<``T₁``&, const U2&>` is `true`.
465
+
466
  *Effects:* Assigns `u.first` to the first element of `*this` and
467
  `u.second` to the second element of `*this`.
468
 
 
 
 
 
 
 
469
  *Returns:* `*this`.
470
 
471
  ``` cpp
472
+ template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&& u);
473
  ```
474
 
475
+ *Constraints:*
476
+
477
+ - `sizeof...(Types)` is 2 and
478
+ - `is_assignable_v<``T₀``&, U1>` is `true`, and
479
+ - `is_assignable_v<``T₁``&, U2>` is `true`.
480
+
481
  *Effects:* Assigns `std::forward<U1>(u.first)` to the first element of
482
  `*this` and
483
  `std::forward<U2>(u.second)` to the second element of `*this`.
484
 
 
 
 
 
 
 
485
  *Returns:* `*this`.
486
 
487
  #### `swap` <a id="tuple.swap">[[tuple.swap]]</a>
488
 
489
  ``` cpp
490
+ constexpr void swap(tuple& rhs) noexcept(see below);
491
  ```
492
 
493
+ *Preconditions:* Each element in `*this` is swappable
494
+ with [[swappable.requirements]] the corresponding element in `rhs`.
495
 
496
  *Effects:* Calls `swap` for each element in `*this` and its
497
  corresponding element in `rhs`.
498
 
499
  *Remarks:* The expression inside `noexcept` is equivalent to the logical
 
506
  where Tᵢ is the iᵗʰ type in `Types`.
507
 
508
  *Throws:* Nothing unless one of the element-wise `swap` calls throws an
509
  exception.
510
 
511
+ ### Tuple creation functions <a id="tuple.creation">[[tuple.creation]]</a>
512
 
513
+ In the function descriptions that follow, the members of a template
514
+ parameter pack `XTypes` are denoted by `X`ᵢ for i in \[`0`,
515
  `sizeof...(`*X*`Types)`) in order, where indexing is zero-based.
516
 
517
  ``` cpp
518
  template<class... TTypes>
519
+ constexpr tuple<unwrap_ref_decay_t<TTypes>...> make_tuple(TTypes&&... t);
520
  ```
521
 
522
+ *Returns:*
523
+ `tuple<unwrap_ref_decay_t<TTypes>...>(std::forward<TTypes>(t)...)`.
 
 
 
 
524
 
525
  [*Example 1*:
526
 
527
  ``` cpp
528
  int i; float j;
 
538
  constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&... t) noexcept;
539
  ```
540
 
541
  *Effects:* Constructs a tuple of references to the arguments in `t`
542
  suitable for forwarding as arguments to a function. Because the result
543
+ may contain references to temporary objects, a program shall ensure that
544
+ the return value of this function does not outlive any of its arguments
545
+ (e.g., the program should typically not store the result in a named
546
+ variable).
547
 
548
  *Returns:* `tuple<TTypes&&...>(std::forward<TTypes>(t)...)`.
549
 
550
  ``` cpp
551
  template<class... TTypes>
 
576
 
577
  In the following paragraphs, let `Tᵢ` be the iᵗʰ type in `Tuples`, `Uᵢ`
578
  be `remove_reference_t<T`ᵢ`>`, and `tpᵢ` be the iᵗʰ parameter in the
579
  function parameter pack `tpls`, where all indexing is zero-based.
580
 
581
+ *Preconditions:* For all i, `Uᵢ` is the type cvᵢ `tuple<``Argsᵢ``...>`,
582
  where cvᵢ is the (possibly empty) iᵗʰ *cv-qualifier-seq* and `Argsᵢ` is
583
+ the template parameter pack representing the element types in `Uᵢ`. Let
584
+ `A_ik` be the kᵗʰ type in `Argsᵢ`. For all `A_ik` the following
585
+ requirements are met:
586
 
587
  - If `Tᵢ` is deduced as an lvalue reference type, then
588
  `is_constructible_v<``A_ik``, `cvᵢ `A_ik``&> == true`, otherwise
589
  - `is_constructible_v<``A_ik``, `cvᵢ `A_ik``&&> == true`.
590
 
591
+ *Remarks:* The types in `CTypes` are equal to the ordered sequence of
592
+ the extended types `Args₀``..., ``Args₁``..., `…`, ``Args_n-1``...`,
593
  where n is equal to `sizeof...(Tuples)`. Let `eᵢ``...` be the iᵗʰ
594
  ordered sequence of tuple elements of the resulting `tuple` object
595
  corresponding to the type sequence `Argsᵢ`.
596
 
597
  *Returns:* A `tuple` object constructed by initializing the kᵢᵗʰ type
 
602
  ```
603
 
604
  for each valid kᵢ and each group `eᵢ` in order.
605
 
606
  [*Note 1*: An implementation may support additional types in the
607
+ template parameter pack `Tuples` that support the `tuple`-like protocol,
608
+ such as `pair` and `array`. — *end note*]
609
 
610
+ ### Calling a function with a `tuple` of arguments <a id="tuple.apply">[[tuple.apply]]</a>
611
 
612
  ``` cpp
613
  template<class F, class Tuple>
614
  constexpr decltype(auto) apply(F&& f, Tuple&& t);
615
  ```
616
 
617
  *Effects:* Given the exposition-only function:
618
 
619
  ``` cpp
620
  template<class F, class Tuple, size_t... I>
621
+ constexpr decltype(auto) apply-impl(F&& f, Tuple&& t, index_sequence<I...>) {
622
+ // exposition only
623
+ return INVOKE(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...); // see [func.require]
624
  }
625
  ```
626
 
627
  Equivalent to:
628
 
629
  ``` cpp
630
+ return apply-impl(std::forward<F>(f), std::forward<Tuple>(t),
631
+ make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
632
  ```
633
 
634
  ``` cpp
635
  template<class T, class Tuple>
636
  constexpr T make_from_tuple(Tuple&& t);
 
638
 
639
  *Effects:* Given the exposition-only function:
640
 
641
  ``` cpp
642
  template<class T, class Tuple, size_t... I>
643
+ constexpr T make-from-tuple-impl(Tuple&& t, index_sequence<I...>) { // exposition only
644
  return T(get<I>(std::forward<Tuple>(t))...);
645
  }
646
  ```
647
 
648
  Equivalent to:
649
 
650
  ``` cpp
651
+ return make-from-tuple-impl<T>(
652
+ forward<Tuple>(t),
653
+ make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
654
  ```
655
 
656
  [*Note 1*: The type of `T` must be supplied as an explicit template
657
  parameter, as it cannot be deduced from the argument
658
  list. — *end note*]
659
 
660
+ ### Tuple helper classes <a id="tuple.helper">[[tuple.helper]]</a>
661
 
662
  ``` cpp
663
  template<class T> struct tuple_size;
664
  ```
665
 
666
+ All specializations of `tuple_size` meet the *Cpp17UnaryTypeTrait*
667
+ requirements [[meta.rqmts]] with a base characteristic of
668
+ `integral_constant<size_t, N>` for some `N`.
669
 
670
  ``` cpp
671
  template<class... Types>
672
+ struct tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
673
  ```
674
 
675
  ``` cpp
676
  template<size_t I, class... Types>
677
+ struct tuple_element<I, tuple<Types...>> {
 
678
  using type = TI;
679
  };
680
  ```
681
 
682
+ *Mandates:* `I` < `sizeof...(Types)`.
 
683
 
684
+ *Type:* `TI` is the type of the `I`ᵗʰ element of `Types`, where indexing
685
  is zero-based.
686
 
687
  ``` cpp
688
+ template<class T> struct tuple_size<const T>;
 
 
689
  ```
690
 
691
+ Let `TS` denote `tuple_size<T>` of the cv-unqualified type `T`. If the
692
+ expression `TS::value` is well-formed when treated as an unevaluated
693
+ operand, then each specialization of the template meets the
694
+ *Cpp17UnaryTypeTrait* requirements [[meta.rqmts]] with a base
695
  characteristic of
696
 
697
  ``` cpp
698
  integral_constant<size_t, TS::value>
699
  ```
700
 
701
+ Otherwise, it has no member `value`.
702
 
703
+ Access checking is performed as if in a context unrelated to `TS` and
704
  `T`. Only the validity of the immediate context of the expression is
705
  considered.
706
 
707
  [*Note 1*: The compilation of the expression can result in side effects
708
  such as the instantiation of class template specializations and function
709
  template specializations, the generation of implicitly-defined
710
  functions, and so on. Such side effects are not in the “immediate
711
  context” and can result in the program being ill-formed. — *end note*]
712
 
713
  In addition to being available via inclusion of the `<tuple>` header,
714
+ the template is available when any of the headers `<array>`, `<ranges>`,
715
  or `<utility>` are included.
716
 
717
  ``` cpp
718
+ template<size_t I, class T> struct tuple_element<I, const T>;
 
 
719
  ```
720
 
721
+ Let `TE` denote `tuple_element_t<I, T>` of the cv-unqualified type `T`.
722
+ Then each specialization of the template meets the
723
+ *Cpp17TransformationTrait* requirements [[meta.rqmts]] with a member
724
+ typedef `type` that names the type `add_const_t<TE>`.
 
 
 
 
725
 
726
  In addition to being available via inclusion of the `<tuple>` header,
727
+ the template is available when any of the headers `<array>`, `<ranges>`,
728
  or `<utility>` are included.
729
 
730
+ ### Element access <a id="tuple.elem">[[tuple.elem]]</a>
731
 
732
  ``` cpp
733
  template<size_t I, class... Types>
734
  constexpr tuple_element_t<I, tuple<Types...>>&
735
  get(tuple<Types...>& t) noexcept;
 
741
  get(const tuple<Types...>& t) noexcept; // Note B
742
  template<size_t I, class... Types>
743
  constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
744
  ```
745
 
746
+ *Mandates:* `I` < `sizeof...(Types)`.
 
747
 
748
+ *Returns:* A reference to the `I`ᵗʰ element of `t`, where indexing is
749
  zero-based.
750
 
751
+ [*Note 1*: \[Note A\]If a type `T` in `Types` is some reference type
752
+ `X&`, the return type is `X&`, not `X&&`. However, if the element type
753
+ is a non-reference type `T`, the return type is `T&&`. — *end note*]
754
 
755
+ [*Note 2*: \[Note B\]Constness is shallow. If a type `T` in `Types` is
756
+ some reference type `X&`, the return type is `X&`, not `const X&`.
757
+ However, if the element type is a non-reference type `T`, the return
758
+ type is `const T&`. This is consistent with how constness is defined to
759
+ work for member variables of reference type. — *end note*]
760
 
761
  ``` cpp
762
  template<class T, class... Types>
763
  constexpr T& get(tuple<Types...>& t) noexcept;
764
  template<class T, class... Types>
 
767
  constexpr const T& get(const tuple<Types...>& t) noexcept;
768
  template<class T, class... Types>
769
  constexpr const T&& get(const tuple<Types...>&& t) noexcept;
770
  ```
771
 
772
+ *Mandates:* The type `T` occurs exactly once in `Types`.
 
773
 
774
  *Returns:* A reference to the element of `t` corresponding to the type
775
+ `T` in `Types`.
776
 
777
  [*Example 1*:
778
 
779
  ``` cpp
780
  const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6);
781
+ const int& i1 = get<int>(t); // OK, i1 has value 1
782
+ const int& i2 = get<const int>(t); // OK, i2 has value 2
783
+ const double& d = get<double>(t); // error: type double is not unique within t
784
  ```
785
 
786
  — *end example*]
787
 
788
  [*Note 1*: The reason `get` is a non-member function is that if this
789
  functionality had been provided as a member function, code where the
790
  type depended on a template parameter would have required using the
791
  `template` keyword. — *end note*]
792
 
793
+ ### Relational operators <a id="tuple.rel">[[tuple.rel]]</a>
794
 
795
  ``` cpp
796
  template<class... TTypes, class... UTypes>
797
  constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
798
  ```
799
 
800
+ *Mandates:* For all `i`, where 0 `i` < `sizeof...(TTypes)`,
801
  `get<i>(t) == get<i>(u)` is a valid expression returning a type that is
802
+ convertible to `bool`. `sizeof...(TTypes)` equals `sizeof...(UTypes)`.
803
 
804
  *Returns:* `true` if `get<i>(t) == get<i>(u)` for all `i`, otherwise
805
  `false`. For any two zero-length tuples `e` and `f`, `e == f` returns
806
  `true`.
807
 
 
809
  zeroth index upwards. No comparisons or element accesses are performed
810
  after the first equality comparison that evaluates to `false`.
811
 
812
  ``` cpp
813
  template<class... TTypes, class... UTypes>
814
+ constexpr common_comparison_category_t<synth-three-way-result<TTypes, UTypes>...>
815
+ operator<=>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
816
  ```
817
 
818
+ *Effects:* Performs a lexicographical comparison between `t` and `u`.
819
+ For any two zero-length tuples `t` and `u`, `t <=> u` returns
820
+ `strong_ordering::equal`. Otherwise, equivalent to:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
821
 
822
  ``` cpp
823
+ if (auto c = synth-three-way(get<0>(t), get<0>(u)); c != 0) return c;
824
+ return $t_tail$ <=> $u_tail$;
825
  ```
826
 
827
+ where `r_tail` for some tuple `r` is a tuple containing all but the
828
+ first element of `r`.
829
 
830
+ [*Note 1*: The above definition does not require `tₜₐᵢₗ` (or `uₜₐᵢₗ`)
831
+ to be constructed. It may not even be possible, as `t` and `u` are not
832
+ required to be copy constructible. Also, all comparison functions are
833
+ short circuited; they do not perform element accesses beyond what is
834
+ required to determine the result of the comparison. — *end note*]
 
835
 
836
+ ### Tuple traits <a id="tuple.traits">[[tuple.traits]]</a>
837
 
838
  ``` cpp
839
  template<class... Types, class Alloc>
840
  struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
841
  ```
842
 
843
+ *Preconditions:* `Alloc` meets the *Cpp17Allocator* requirements
844
+ ([[cpp17.allocator]]).
845
 
846
  [*Note 1*: Specialization of this trait informs other library
847
  components that `tuple` can be constructed with an allocator, even
848
  though it does not have a nested `allocator_type`. — *end note*]
849
 
850
+ ### Tuple specialized algorithms <a id="tuple.special">[[tuple.special]]</a>
851
 
852
  ``` cpp
853
  template<class... Types>
854
+ constexpr void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
855
  ```
856
 
857
+ *Constraints:* `is_swappable_v<T>` is `true` for every type `T` in
858
+ `Types`.
859
+
860
+ *Remarks:* The expression inside `noexcept` is equivalent to:
861
 
862
  ``` cpp
863
  noexcept(x.swap(y))
864
  ```
865