From Jason Turner

[tuple.tuple]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmplaiqyf5w/{from.md → to.md} +172 -539
tmp/tmplaiqyf5w/{from.md → to.md} RENAMED
@@ -4,64 +4,71 @@
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
 
51
  template<class... UTypes>
52
- tuple& operator=(const tuple<UTypes...>&);
53
  template<class... UTypes>
54
- tuple& operator=(tuple<UTypes...>&&);
55
 
56
  template<class U1, class U2>
57
- tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2
58
  template<class U1, class U2>
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>
@@ -75,186 +82,211 @@ namespace std {
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
 
253
  *Effects:* Equivalent to the preceding constructors except that each
254
  element is constructed with uses-allocator
255
- construction ([[allocator.uses.construction]]).
256
 
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
@@ -262,31 +294,30 @@ 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ᵢ>
@@ -295,74 +326,76 @@ is_nothrow_move_assignable_v<Tᵢ>
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
@@ -375,405 +408,5 @@ is_nothrow_swappable_v<Tᵢ>
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.
557
-
558
- *Type:* `TI` is the type of the `I`th element of `Types`, where indexing
559
- is zero-based.
560
-
561
- ``` cpp
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>
681
- constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
682
- ```
683
-
684
- *Requires:* For all `i`, where `0 <= i` and `i < sizeof...(TTypes)`,
685
- `get<i>(t) == get<i>(u)` is a valid expression returning a type that is
686
- convertible to `bool`. `sizeof...(TTypes)` `==` `sizeof...(UTypes)`.
687
-
688
- *Returns:* `true` if `get<i>(t) == get<i>(u)` for all `i`, otherwise
689
- `false`. For any two zero-length tuples `e` and `f`, `e == f` returns
690
- `true`.
691
-
692
- *Effects:* The elementary comparisons are performed in order from the
693
- zeroth index upwards. No comparisons or element accesses are performed
694
- after the first equality comparison that evaluates to `false`.
695
-
696
- ``` cpp
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:
708
- `(bool)(get<0>(t) < get<0>(u)) || (!(bool)(get<0>(u) < get<0>(t)) && t`ₜₐᵢₗ` < u`ₜₐᵢₗ`)`,
709
- where `r`ₜₐᵢₗ for some tuple `r` is a tuple containing all but the first
710
- element of `r`. For any two zero-length tuples `e` and `f`, `e < f`
711
- returns `false`.
712
-
713
- ``` cpp
714
- template<class... TTypes, class... UTypes>
715
- constexpr bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
716
- ```
717
-
718
- *Returns:* `!(t == u)`.
719
-
720
- ``` cpp
721
- template<class... TTypes, class... UTypes>
722
- constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
723
- ```
724
-
725
- *Returns:* `u < t`.
726
-
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>
752
- struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
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
-
 
4
  namespace std {
5
  template<class... Types>
6
  class tuple {
7
  public:
8
  // [tuple.cnstr], tuple construction
9
+ constexpr explicit(see below) tuple();
10
+ constexpr explicit(see below) tuple(const Types&...); // only if sizeof...(Types) >= 1
11
  template<class... UTypes>
12
+ constexpr explicit(see below) tuple(UTypes&&...); // only if sizeof...(Types) >= 1
13
 
14
  tuple(const tuple&) = default;
15
  tuple(tuple&&) = default;
16
 
17
  template<class... UTypes>
18
+ constexpr explicit(see below) tuple(const tuple<UTypes...>&);
19
  template<class... UTypes>
20
+ constexpr explicit(see below) tuple(tuple<UTypes...>&&);
21
 
22
  template<class U1, class U2>
23
+ constexpr explicit(see below) tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2
24
  template<class U1, class U2>
25
+ constexpr explicit(see below) tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2
26
 
27
  // allocator-extended constructors
28
  template<class Alloc>
29
+ constexpr explicit(see below)
30
  tuple(allocator_arg_t, const Alloc& a);
31
  template<class Alloc>
32
+ constexpr explicit(see below)
33
+ tuple(allocator_arg_t, const Alloc& a, const Types&...);
34
  template<class Alloc, class... UTypes>
35
+ constexpr explicit(see below)
36
+ tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
37
  template<class Alloc>
38
+ constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
39
  template<class Alloc>
40
+ constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
41
  template<class Alloc, class... UTypes>
42
+ constexpr explicit(see below)
43
+ tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
44
  template<class Alloc, class... UTypes>
45
+ constexpr explicit(see below)
46
+ tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
47
  template<class Alloc, class U1, class U2>
48
+ constexpr explicit(see below)
49
+ tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
50
  template<class Alloc, class U1, class U2>
51
+ constexpr explicit(see below)
52
+ tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
53
 
54
  // [tuple.assign], tuple assignment
55
+ constexpr tuple& operator=(const tuple&);
56
+ constexpr tuple& operator=(tuple&&) noexcept(see below);
57
 
58
  template<class... UTypes>
59
+ constexpr tuple& operator=(const tuple<UTypes...>&);
60
  template<class... UTypes>
61
+ constexpr tuple& operator=(tuple<UTypes...>&&);
62
 
63
  template<class U1, class U2>
64
+ constexpr tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2
65
  template<class U1, class U2>
66
+ constexpr tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2
67
 
68
  // [tuple.swap], tuple swap
69
+ constexpr void swap(tuple&) noexcept(see below);
70
  };
71
 
72
  template<class... UTypes>
73
  tuple(UTypes...) -> tuple<UTypes...>;
74
  template<class T1, class T2>
 
82
  }
83
  ```
84
 
85
  #### Construction <a id="tuple.cnstr">[[tuple.cnstr]]</a>
86
 
87
+ In the descriptions that follow, let i be in the range \[`0`,
88
+ `sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`, and `Uᵢ`
89
+ be the iᵗʰ type in a template parameter pack named `UTypes`, where
90
+ indexing is zero-based.
91
+
92
  For each `tuple` constructor, an exception is thrown only if the
93
  construction of one of the types in `Types` throws an exception.
94
 
95
+ The defaulted move and copy constructor, respectively, of `tuple` is a
96
+ constexpr function if and only if all required element-wise
97
+ initializations for move and copy, respectively, would satisfy the
98
  requirements for a constexpr function. The defaulted move and copy
99
+ constructor of `tuple<>` are constexpr functions.
100
 
101
+ If `is_trivially_destructible_v<Tᵢ>` is `true` for all `Tᵢ`, then the
102
+ destructor of `tuple` is trivial.
 
 
 
 
 
103
 
104
  ``` cpp
105
+ constexpr explicit(see below) tuple();
106
  ```
107
 
108
+ *Constraints:* `is_default_constructible_v<``Tᵢ``>` is `true` for all i.
109
+
110
  *Effects:* Value-initializes each element.
111
 
112
+ *Remarks:* The expression inside `explicit` evaluates to `true` if and
113
+ only if `Tᵢ` is not copy-list-initializable from an empty list for at
114
+ least one i.
115
 
116
+ [*Note 1*: This behavior can be implemented with a trait that checks
 
 
 
 
 
 
117
  whether a `const ``Tᵢ``&` can be initialized with `{}`. — *end note*]
118
 
119
  ``` cpp
120
+ constexpr explicit(see below) tuple(const Types&...);
121
  ```
122
 
123
+ *Constraints:* `sizeof...(Types)` ≥ 1 and
124
+ `is_copy_constructible_v<``Tᵢ``>` is `true` for all i.
125
+
126
  *Effects:* Initializes each element with the value of the corresponding
127
  parameter.
128
 
129
+ *Remarks:* The expression inside `explicit` is equivalent to:
 
 
 
130
 
131
  ``` cpp
132
+ !conjunction_v<is_convertible<const Types&, Types>...>
133
  ```
134
 
135
+ ``` cpp
136
+ template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&... u);
137
+ ```
138
+
139
+ *Constraints:* `sizeof...(Types)` equals `sizeof...(UTypes)` and
140
+ `sizeof...(Types)` ≥ 1 and `is_constructible_v<``Tᵢ``, ``Uᵢ``>` is
141
+ `true` for all i.
142
+
143
  *Effects:* Initializes the elements in the tuple with the corresponding
144
  value in `std::forward<UTypes>(u)`.
145
 
146
+ *Remarks:* The expression inside `explicit` is equivalent to:
147
+
148
+ ``` cpp
149
+ !conjunction_v<is_convertible<UTypes, Types>...>
150
+ ```
151
 
152
  ``` cpp
153
  tuple(const tuple& u) = default;
154
  ```
155
 
156
+ *Mandates:* `is_copy_constructible_v<``Tᵢ``>` is `true` for all i.
157
 
158
  *Effects:* Initializes each element of `*this` with the corresponding
159
  element of `u`.
160
 
161
  ``` cpp
162
  tuple(tuple&& u) = default;
163
  ```
164
 
165
+ *Constraints:* `is_move_constructible_v<``Tᵢ``>` is `true` for all i.
166
 
167
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
168
  `std::forward<``Tᵢ``>(get<`i`>(u))`.
169
 
170
  ``` cpp
171
+ template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u);
172
  ```
173
 
174
+ *Constraints:*
 
175
 
176
+ - `sizeof...(Types)` equals `sizeof...(UTypes)` and
 
 
 
177
  - `is_constructible_v<``Tᵢ``, const ``Uᵢ``&>` is `true` for all i, and
178
+ - either `sizeof...(Types)` is not 1, or (when `Types...` expands to `T`
179
+ and `UTypes...` expands to `U`)
180
+ `is_convertible_v<const tuple<U>&, T>`,
181
+ `is_constructible_v<T, const tuple<U>&>`, and `is_same_v<T, U>` are
182
+ all `false`.
183
 
184
+ *Effects:* Initializes each element of `*this` with the corresponding
185
+ element of `u`.
186
+
187
+ *Remarks:* The expression inside `explicit` is equivalent to:
188
+
189
+ ``` cpp
190
+ !conjunction_v<is_convertible<const UTypes&, Types>...>
191
+ ```
192
 
193
  ``` cpp
194
+ template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u);
195
  ```
196
 
197
+ *Constraints:*
198
+
199
+ - `sizeof...(Types)` equals `sizeof...(UTypes)`, and
200
+ - `is_constructible_v<``Tᵢ``, ``Uᵢ``>` is `true` for all i, and
201
+ - either `sizeof...(Types)` is not 1, or (when `Types...` expands to `T`
202
+ and `UTypes...` expands to `U`) `is_convertible_v<tuple<U>, T>`,
203
+ `is_constructible_v<T, tuple<U>>`, and `is_same_v<T, U>` are all
204
+ `false`.
205
+
206
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
207
  `std::forward<``Uᵢ``>(get<`i`>(u))`.
208
 
209
+ *Remarks:* The expression inside `explicit` is equivalent to:
 
210
 
211
+ ``` cpp
212
+ !conjunction_v<is_convertible<UTypes, Types>...>
213
+ ```
 
 
 
 
 
 
214
 
215
  ``` cpp
216
+ template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>& u);
217
  ```
218
 
219
+ *Constraints:*
220
+
221
+ - `sizeof...(Types)` is 2,
222
+ - `is_constructible_v<``T₀``, const U1&>` is `true`, and
223
+ - `is_constructible_v<``T₁``, const U2&>` is `true`.
224
+
225
  *Effects:* Initializes the first element with `u.first` and the second
226
  element with `u.second`.
227
 
228
+ The expression inside `explicit` is equivalent to:
 
 
229
 
230
+ ``` cpp
231
+ !is_convertible_v<const U1&, $T_0$> || !is_convertible_v<const U2&, $T_1$>
232
+ ```
233
 
234
  ``` cpp
235
+ template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&& u);
236
  ```
237
 
238
+ *Constraints:*
239
+
240
+ - `sizeof...(Types)` is 2,
241
+ - `is_constructible_v<``T₀``, U1>` is `true`, and
242
+ - `is_constructible_v<``T₁``, U2>` is `true`.
243
+
244
  *Effects:* Initializes the first element with
245
  `std::forward<U1>(u.first)` and the second element with
246
  `std::forward<U2>(u.second)`.
247
 
248
+ The expression inside `explicit` is equivalent to:
 
 
249
 
250
+ ``` cpp
251
+ !is_convertible_v<U1, $T_0$> || !is_convertible_v<U2, $T_1$>
252
+ ```
253
 
254
  ``` cpp
255
  template<class Alloc>
256
+ constexpr explicit(see below)
257
  tuple(allocator_arg_t, const Alloc& a);
258
  template<class Alloc>
259
+ constexpr explicit(see below)
260
+ tuple(allocator_arg_t, const Alloc& a, const Types&...);
261
  template<class Alloc, class... UTypes>
262
+ constexpr explicit(see below)
263
+ tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
264
  template<class Alloc>
265
+ constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
266
  template<class Alloc>
267
+ constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
268
  template<class Alloc, class... UTypes>
269
+ constexpr explicit(see below)
270
+ tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
271
  template<class Alloc, class... UTypes>
272
+ constexpr explicit(see below)
273
+ tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
274
  template<class Alloc, class U1, class U2>
275
+ constexpr explicit(see below)
276
+ tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
277
  template<class Alloc, class U1, class U2>
278
+ constexpr explicit(see below)
279
+ tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
280
  ```
281
 
282
+ *Preconditions:* `Alloc` meets the *Cpp17Allocator* requirements
283
+ ([[cpp17.allocator]]).
284
 
285
  *Effects:* Equivalent to the preceding constructors except that each
286
  element is constructed with uses-allocator
287
+ construction [[allocator.uses.construction]].
288
 
289
  #### Assignment <a id="tuple.assign">[[tuple.assign]]</a>
290
 
291
  For each `tuple` assignment operator, an exception is thrown only if the
292
  assignment of one of the types in `Types` throws an exception. In the
 
294
  `sizeof...(Types)`) in order, `Tᵢ` be the iᵗʰ type in `Types`, and `Uᵢ`
295
  be the iᵗʰ type in a template parameter pack named `UTypes`, where
296
  indexing is zero-based.
297
 
298
  ``` cpp
299
+ constexpr tuple& operator=(const tuple& u);
300
  ```
301
 
302
  *Effects:* Assigns each element of `u` to the corresponding element of
303
  `*this`.
304
 
305
+ *Remarks:* This operator is defined as deleted unless
306
  `is_copy_assignable_v<``Tᵢ``>` is `true` for all i.
307
 
308
  *Returns:* `*this`.
309
 
310
  ``` cpp
311
+ constexpr tuple& operator=(tuple&& u) noexcept(see below);
312
  ```
313
 
314
+ *Constraints:* `is_move_assignable_v<``Tᵢ``>` is `true` for all i.
315
+
316
  *Effects:* For all i, assigns `std::forward<``Tᵢ``>(get<`i`>(u))` to
317
  `get<`i`>(*this)`.
318
 
 
 
 
319
  *Remarks:* The expression inside `noexcept` is equivalent to the logical
320
  <span class="smallcaps">and</span> of the following expressions:
321
 
322
  ``` cpp
323
  is_nothrow_move_assignable_v<Tᵢ>
 
326
  where Tᵢ is the iᵗʰ type in `Types`.
327
 
328
  *Returns:* `*this`.
329
 
330
  ``` cpp
331
+ template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>& u);
332
  ```
333
 
334
+ *Constraints:*
335
+
336
+ - `sizeof...(Types)` equals `sizeof...(UTypes)` and
337
+ - `is_assignable_v<``Tᵢ``&, const ``Uᵢ``&>` is `true` for all i.
338
+
339
  *Effects:* Assigns each element of `u` to the corresponding element of
340
  `*this`.
341
 
 
 
 
 
342
  *Returns:* `*this`.
343
 
344
  ``` cpp
345
+ template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&& u);
346
  ```
347
 
348
+ *Constraints:*
349
+
350
+ - `sizeof...(Types)` equals `sizeof...(UTypes)` and
351
+ - `is_assignable_v<``Tᵢ``&, ``Uᵢ``>` is `true` for all i.
352
+
353
  *Effects:* For all i, assigns `std::forward<``Uᵢ``>(get<`i`>(u))` to
354
  `get<`i`>(*this)`.
355
 
 
 
 
 
356
  *Returns:* `*this`.
357
 
358
  ``` cpp
359
+ template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>& u);
360
  ```
361
 
362
+ *Constraints:*
363
+
364
+ - `sizeof...(Types)` is 2 and
365
+ - `is_assignable_v<``T₀``&, const U1&>` is `true`, and
366
+ - `is_assignable_v<``T₁``&, const U2&>` is `true`.
367
+
368
  *Effects:* Assigns `u.first` to the first element of `*this` and
369
  `u.second` to the second element of `*this`.
370
 
 
 
 
 
 
 
371
  *Returns:* `*this`.
372
 
373
  ``` cpp
374
+ template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&& u);
375
  ```
376
 
377
+ *Constraints:*
378
+
379
+ - `sizeof...(Types)` is 2 and
380
+ - `is_assignable_v<``T₀``&, U1>` is `true`, and
381
+ - `is_assignable_v<``T₁``&, U2>` is `true`.
382
+
383
  *Effects:* Assigns `std::forward<U1>(u.first)` to the first element of
384
  `*this` and
385
  `std::forward<U2>(u.second)` to the second element of `*this`.
386
 
 
 
 
 
 
 
387
  *Returns:* `*this`.
388
 
389
  #### `swap` <a id="tuple.swap">[[tuple.swap]]</a>
390
 
391
  ``` cpp
392
+ constexpr void swap(tuple& rhs) noexcept(see below);
393
  ```
394
 
395
+ *Preconditions:* Each element in `*this` is swappable
396
+ with [[swappable.requirements]] the corresponding element in `rhs`.
397
 
398
  *Effects:* Calls `swap` for each element in `*this` and its
399
  corresponding element in `rhs`.
400
 
401
  *Remarks:* The expression inside `noexcept` is equivalent to the logical
 
408
  where Tᵢ is the iᵗʰ type in `Types`.
409
 
410
  *Throws:* Nothing unless one of the element-wise `swap` calls throws an
411
  exception.
412