From Jason Turner

[tuple.tuple]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpby1fb57l/{from.md → to.md} +295 -72
tmp/tmpby1fb57l/{from.md → to.md} RENAMED
@@ -12,19 +12,30 @@ namespace std {
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);
@@ -36,39 +47,71 @@ namespace std {
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>
@@ -92,17 +135,19 @@ indexing is zero-based.
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.
@@ -134,23 +179,43 @@ parameter.
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.
@@ -166,91 +231,108 @@ tuple(tuple&& u) = default;
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)
@@ -263,26 +345,41 @@ template<class Alloc, class... UTypes>
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
 
@@ -300,13 +397,24 @@ 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
  ```
@@ -314,19 +422,31 @@ constexpr tuple& operator=(tuple&& u) noexcept(see below);
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ᵢ>
324
  ```
325
 
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
  ```
@@ -339,10 +459,24 @@ template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>& u);
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:*
@@ -353,10 +487,24 @@ template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&& u);
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:*
@@ -368,10 +516,25 @@ template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>& u);
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:*
@@ -384,29 +547,89 @@ template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&& u);
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
402
- <span class="smallcaps">and</span> of the following expressions:
 
403
 
404
- ``` cpp
405
- is_nothrow_swappable_v<Tᵢ>
406
- ```
407
 
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
 
 
 
 
 
 
 
 
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(tuple<UTypes...>&);
19
  template<class... UTypes>
20
  constexpr explicit(see below) tuple(const tuple<UTypes...>&);
21
  template<class... UTypes>
22
  constexpr explicit(see below) tuple(tuple<UTypes...>&&);
23
+ template<class... UTypes>
24
+ constexpr explicit(see below) tuple(const tuple<UTypes...>&&);
25
 
26
+ template<class U1, class U2>
27
+ constexpr explicit(see below) tuple(pair<U1, U2>&); // only if sizeof...(Types) == 2
28
  template<class U1, class U2>
29
  constexpr explicit(see below) tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2
30
  template<class U1, class U2>
31
  constexpr explicit(see below) tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2
32
+ template<class U1, class U2>
33
+ constexpr explicit(see below) tuple(const pair<U1, U2>&&); // only if sizeof...(Types) == 2
34
+
35
+ template<tuple-like UTuple>
36
+ constexpr explicit(see below) tuple(UTuple&&);
37
 
38
  // allocator-extended constructors
39
  template<class Alloc>
40
  constexpr explicit(see below)
41
  tuple(allocator_arg_t, const Alloc& a);
 
47
  tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
48
  template<class Alloc>
49
  constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
50
  template<class Alloc>
51
  constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
52
+ template<class Alloc, class... UTypes>
53
+ constexpr explicit(see below)
54
+ tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&);
55
  template<class Alloc, class... UTypes>
56
  constexpr explicit(see below)
57
  tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
58
  template<class Alloc, class... UTypes>
59
  constexpr explicit(see below)
60
  tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
61
+ template<class Alloc, class... UTypes>
62
+ constexpr explicit(see below)
63
+ tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&&);
64
+ template<class Alloc, class U1, class U2>
65
+ constexpr explicit(see below)
66
+ tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&);
67
  template<class Alloc, class U1, class U2>
68
  constexpr explicit(see below)
69
  tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
70
  template<class Alloc, class U1, class U2>
71
  constexpr explicit(see below)
72
  tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
73
+ template<class Alloc, class U1, class U2>
74
+ constexpr explicit(see below)
75
+ tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&&);
76
+
77
+ template<class Alloc, exposition onlyconceptnc{tuple-like} UTuple>
78
+ constexpr explicit(see below) tuple(allocator_arg_t, const Alloc& a, UTuple&&);
79
 
80
  // [tuple.assign], tuple assignment
81
  constexpr tuple& operator=(const tuple&);
82
+ constexpr const tuple& operator=(const tuple&) const;
83
  constexpr tuple& operator=(tuple&&) noexcept(see below);
84
+ constexpr const tuple& operator=(tuple&&) const;
85
 
86
  template<class... UTypes>
87
  constexpr tuple& operator=(const tuple<UTypes...>&);
88
+ template<class... UTypes>
89
+ constexpr const tuple& operator=(const tuple<UTypes...>&) const;
90
  template<class... UTypes>
91
  constexpr tuple& operator=(tuple<UTypes...>&&);
92
+ template<class... UTypes>
93
+ constexpr const tuple& operator=(tuple<UTypes...>&&) const;
94
 
95
  template<class U1, class U2>
96
  constexpr tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2
97
+ template<class U1, class U2>
98
+ constexpr const tuple& operator=(const pair<U1, U2>&) const;
99
+ // only if sizeof...(Types) == 2
100
  template<class U1, class U2>
101
  constexpr tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2
102
+ template<class U1, class U2>
103
+ constexpr const tuple& operator=(pair<U1, U2>&&) const; // only if sizeof...(Types) == 2
104
+
105
+ template<exposition onlyconceptnc{tuple-like} UTuple>
106
+ constexpr tuple& operator=(UTuple&&);
107
+ template<exposition onlyconceptnc{tuple-like}@ UTuple>
108
+ constexpr const tuple& operator=(UTuple&&) const;
109
 
110
  // [tuple.swap], tuple swap
111
  constexpr void swap(tuple&) noexcept(see below);
112
+ constexpr void swap(const tuple&) const noexcept(see below);
113
  };
114
 
115
  template<class... UTypes>
116
  tuple(UTypes...) -> tuple<UTypes...>;
117
  template<class T1, class T2>
 
135
  For each `tuple` constructor, an exception is thrown only if the
136
  construction of one of the types in `Types` throws an exception.
137
 
138
  The defaulted move and copy constructor, respectively, of `tuple` is a
139
  constexpr function if and only if all required element-wise
140
+ initializations for move and copy, respectively, would be
141
+ constexpr-suitable [[dcl.constexpr]]. The defaulted move and copy
142
  constructor of `tuple<>` are constexpr functions.
143
 
144
  If `is_trivially_destructible_v<Tᵢ>` is `true` for all `Tᵢ`, then the
145
  destructor of `tuple` is trivial.
146
 
147
+ The default constructor of `tuple<>` is trivial.
148
+
149
  ``` cpp
150
  constexpr explicit(see below) tuple();
151
  ```
152
 
153
  *Constraints:* `is_default_constructible_v<``Tᵢ``>` is `true` for all i.
 
179
 
180
  ``` cpp
181
  template<class... UTypes> constexpr explicit(see below) tuple(UTypes&&... u);
182
  ```
183
 
184
+ Let *disambiguating-constraint* be:
185
+
186
+ - `negation<is_same<remove_cvref_t<``U₀``>, tuple>>` if
187
+ `sizeof...(Types)` is 1;
188
+ - otherwise,
189
+ `bool_constant<!is_same_v<remove_cvref_t<``U₀``>, allocator_arg_t> || is_- same_v<remove_cvref_t<``T₀``>, allocator_arg_t>>`
190
+ if `sizeof...(Types)` is 2 or 3;
191
+ - otherwise, `true_type`.
192
+
193
+ *Constraints:*
194
+
195
+ - `sizeof...(Types)` equals `sizeof...(UTypes)`,
196
+ - `sizeof...(Types)` ≥ 1, and
197
+ - `conjunction_v<`*`disambiguating-constraint`*`, is_constructible<Types, UTypes>...>`
198
+ is `true`.
199
 
200
  *Effects:* Initializes the elements in the tuple with the corresponding
201
  value in `std::forward<UTypes>(u)`.
202
 
203
  *Remarks:* The expression inside `explicit` is equivalent to:
204
 
205
  ``` cpp
206
  !conjunction_v<is_convertible<UTypes, Types>...>
207
  ```
208
 
209
+ This constructor is defined as deleted if
210
+
211
+ ``` cpp
212
+ (reference_constructs_from_temporary_v<Types, UTypes&&> || ...)
213
+ ```
214
+
215
+ is `true`.
216
+
217
  ``` cpp
218
  tuple(const tuple& u) = default;
219
  ```
220
 
221
  *Mandates:* `is_copy_constructible_v<``Tᵢ``>` is `true` for all i.
 
231
 
232
  *Effects:* For all i, initializes the iᵗʰ element of `*this` with
233
  `std::forward<``Tᵢ``>(get<`i`>(u))`.
234
 
235
  ``` cpp
236
+ template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>& u);
237
  template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>& u);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  template<class... UTypes> constexpr explicit(see below) tuple(tuple<UTypes...>&& u);
239
+ template<class... UTypes> constexpr explicit(see below) tuple(const tuple<UTypes...>&& u);
240
  ```
241
 
242
+ Let `I` be the pack `0, 1, ..., (sizeof...(Types) - 1)`. Let
243
+ *`FWD`*`(u)` be `static_cast<decltype(u)>(u)`.
244
+
245
  *Constraints:*
246
 
247
  - `sizeof...(Types)` equals `sizeof...(UTypes)`, and
248
+ - `(is_constructible_v<Types, decltype(get<I>(`*`FWD`*`(u)))> && ...)`
249
+ is `true`, and
250
  - either `sizeof...(Types)` is not 1, or (when `Types...` expands to `T`
251
+ and `UTypes...` expands to `U`) `is_convertible_v<decltype(u), T>`,
252
+ `is_constructible_v<T, decltype(u)>`, and `is_same_v<T, U>` are all
253
  `false`.
254
 
255
+ *Effects:* For all i, initializes the $i^\textrm{th}$ element of `*this`
256
+ with `get<`i`>(`*`FWD`*`(u))`.
257
 
258
  *Remarks:* The expression inside `explicit` is equivalent to:
259
 
260
  ``` cpp
261
+ !(is_convertible_v<decltype(get<I>(FWD(u))), Types> && ...)
262
  ```
263
 
264
+ The constructor is defined as deleted if
265
+
266
+ ``` cpp
267
+ (reference_constructs_from_temporary_v<Types, decltype(get<I>(FWD(u)))> || ...)
268
+ ```
269
+
270
+ is `true`.
271
+
272
  ``` cpp
273
+ template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>& u);
274
  template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>& u);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  template<class U1, class U2> constexpr explicit(see below) tuple(pair<U1, U2>&& u);
276
+ template<class U1, class U2> constexpr explicit(see below) tuple(const pair<U1, U2>&& u);
277
  ```
278
 
279
+ Let *`FWD`*`(u)` be `static_cast<decltype(u)>(u)`.
280
+
281
  *Constraints:*
282
 
283
  - `sizeof...(Types)` is 2,
284
+ - `is_constructible_v<``T₀``, decltype(get<0>(`*`FWD`*`(u)))>` is
285
+ `true`, and
286
+ - `is_constructible_v<``T₁``, decltype(get<1>(`*`FWD`*`(u)))>` is
287
+ `true`.
288
 
289
+ *Effects:* Initializes the first element with `get<0>(`*`FWD`*`(u))` and
290
+ the second element with `get<1>(`*`FWD`*`(u))`.
 
291
 
292
+ *Remarks:* The expression inside `explicit` is equivalent to:
293
 
294
  ``` cpp
295
+ !is_convertible_v<decltype(get<0>(FWD(u))), $T_0$> ||
296
+ !is_convertible_v<decltype(get<1>(FWD(u))), $T_1$>
297
+ ```
298
+
299
+ The constructor is defined as deleted if
300
+
301
+ ``` cpp
302
+ reference_constructs_from_temporary_v<$T_0$, decltype(get<0>(FWD(u)))> ||
303
+ reference_constructs_from_temporary_v<$T_1$, decltype(get<1>(FWD(u)))>
304
+ ```
305
+
306
+ is `true`.
307
+
308
+ ``` cpp
309
+ template<tuple-like UTuple>
310
+ constexpr explicit(see below) tuple(UTuple&& u);
311
+ ```
312
+
313
+ Let `I` be the pack `0, 1, …, (sizeof...(Types) - 1)`.
314
+
315
+ *Constraints:*
316
+
317
+ - `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
318
+ - `remove_cvref_t<UTuple>` is not a specialization of
319
+ `ranges::subrange`,
320
+ - `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`,
321
+ - `(is_constructible_v<Types, decltype(get<I>(std::forward<UTuple>(u)))> && ...)`
322
+ is `true`, and
323
+ - either `sizeof...(Types)` is not `1`, or (when `Types...` expands to
324
+ `T`) `is_convertible_v<UTuple, T>` and `is_constructible_v<T, UTuple>`
325
+ are both `false`.
326
+
327
+ *Effects:* For all i, initializes the iᵗʰ element of `*this` with
328
+ `get<`i`>(std::forward<UTuple>(u))`.
329
+
330
+ *Remarks:* The expression inside `explicit` is equivalent to:
331
+
332
+ ``` cpp
333
+ !(is_convertible_v<decltype(get<I>(std::forward<UTuple>(u))), Types> && ...)
334
  ```
335
 
336
  ``` cpp
337
  template<class Alloc>
338
  constexpr explicit(see below)
 
345
  tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
346
  template<class Alloc>
347
  constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&);
348
  template<class Alloc>
349
  constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&);
350
+ template<class Alloc, class... UTypes>
351
+ constexpr explicit(see below)
352
+ tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&);
353
  template<class Alloc, class... UTypes>
354
  constexpr explicit(see below)
355
  tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
356
  template<class Alloc, class... UTypes>
357
  constexpr explicit(see below)
358
  tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
359
+ template<class Alloc, class... UTypes>
360
+ constexpr explicit(see below)
361
+ tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&&);
362
+ template<class Alloc, class U1, class U2>
363
+ constexpr explicit(see below)
364
+ tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&);
365
  template<class Alloc, class U1, class U2>
366
  constexpr explicit(see below)
367
  tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
368
  template<class Alloc, class U1, class U2>
369
  constexpr explicit(see below)
370
  tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
371
+ template<class Alloc, class U1, class U2>
372
+ constexpr explicit(see below)
373
+ tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&&);
374
+ template<class Alloc, tuple-like UTuple>
375
+ constexpr explicit(see below)
376
+ tuple(allocator_arg_t, const Alloc& a, UTuple&&);
377
  ```
378
 
379
+ *Preconditions:* `Alloc` meets the *Cpp17Allocator*
380
+ requirements [[allocator.requirements.general]].
381
 
382
  *Effects:* Equivalent to the preceding constructors except that each
383
  element is constructed with uses-allocator
384
  construction [[allocator.uses.construction]].
385
 
 
397
  ```
398
 
399
  *Effects:* Assigns each element of `u` to the corresponding element of
400
  `*this`.
401
 
402
+ *Returns:* `*this`.
403
+
404
  *Remarks:* This operator is defined as deleted unless
405
  `is_copy_assignable_v<``Tᵢ``>` is `true` for all i.
406
 
407
+ ``` cpp
408
+ constexpr const tuple& operator=(const tuple& u) const;
409
+ ```
410
+
411
+ *Constraints:* `(is_copy_assignable_v<const Types> && ...)` is `true`.
412
+
413
+ *Effects:* Assigns each element of `u` to the corresponding element of
414
+ `*this`.
415
+
416
  *Returns:* `*this`.
417
 
418
  ``` cpp
419
  constexpr tuple& operator=(tuple&& u) noexcept(see below);
420
  ```
 
422
  *Constraints:* `is_move_assignable_v<``Tᵢ``>` is `true` for all i.
423
 
424
  *Effects:* For all i, assigns `std::forward<``Tᵢ``>(get<`i`>(u))` to
425
  `get<`i`>(*this)`.
426
 
427
+ *Returns:* `*this`.
428
+
429
+ *Remarks:* The exception specification is equivalent to the logical of
430
+ the following expressions:
431
 
432
  ``` cpp
433
  is_nothrow_move_assignable_v<Tᵢ>
434
  ```
435
 
436
  where Tᵢ is the iᵗʰ type in `Types`.
437
 
438
+ ``` cpp
439
+ constexpr const tuple& operator=(tuple&& u) const;
440
+ ```
441
+
442
+ *Constraints:* `(is_assignable_v<const Types&, Types> && ...)` is
443
+ `true`.
444
+
445
+ *Effects:* For all i, assigns `std::forward<T`ᵢ`>(get<`i`>(u))` to
446
+ `get<`i`>(*this)`.
447
+
448
  *Returns:* `*this`.
449
 
450
  ``` cpp
451
  template<class... UTypes> constexpr tuple& operator=(const tuple<UTypes...>& u);
452
  ```
 
459
  *Effects:* Assigns each element of `u` to the corresponding element of
460
  `*this`.
461
 
462
  *Returns:* `*this`.
463
 
464
+ ``` cpp
465
+ template<class... UTypes> constexpr const tuple& operator=(const tuple<UTypes...>& u) const;
466
+ ```
467
+
468
+ *Constraints:*
469
+
470
+ - `sizeof...(Types)` equals `sizeof...(UTypes)` and
471
+ - `(is_assignable_v<const Types&, const UTypes&> && ...)` is `true`.
472
+
473
+ *Effects:* Assigns each element of `u` to the corresponding element of
474
+ `*this`.
475
+
476
+ *Returns:* `*this`.
477
+
478
  ``` cpp
479
  template<class... UTypes> constexpr tuple& operator=(tuple<UTypes...>&& u);
480
  ```
481
 
482
  *Constraints:*
 
487
  *Effects:* For all i, assigns `std::forward<``Uᵢ``>(get<`i`>(u))` to
488
  `get<`i`>(*this)`.
489
 
490
  *Returns:* `*this`.
491
 
492
+ ``` cpp
493
+ template<class... UTypes> constexpr const tuple& operator=(tuple<UTypes...>&& u) const;
494
+ ```
495
+
496
+ *Constraints:*
497
+
498
+ - `sizeof...(Types)` equals `sizeof...(UTypes)` and
499
+ - `(is_assignable_v<const Types&, UTypes> && ...)` is `true`.
500
+
501
+ *Effects:* For all i, assigns `std::forward<U`ᵢ`>(get<`i`>(u))` to
502
+ `get<`i`>(*this)`.
503
+
504
+ *Returns:* `*this`.
505
+
506
  ``` cpp
507
  template<class U1, class U2> constexpr tuple& operator=(const pair<U1, U2>& u);
508
  ```
509
 
510
  *Constraints:*
 
516
  *Effects:* Assigns `u.first` to the first element of `*this` and
517
  `u.second` to the second element of `*this`.
518
 
519
  *Returns:* `*this`.
520
 
521
+ ``` cpp
522
+ template<class U1, class U2> constexpr const tuple& operator=(const pair<U1, U2>& u) const;
523
+ ```
524
+
525
+ *Constraints:*
526
+
527
+ - `sizeof...(Types)` is 2,
528
+ - `is_assignable_v<const ``T₀``&, const U1&>` is `true`, and
529
+ - `is_assignable_v<const ``T₁``&, const U2&>` is `true`.
530
+
531
+ *Effects:* Assigns `u.first` to the first element and `u.second` to the
532
+ second element.
533
+
534
+ *Returns:* `*this`.
535
+
536
  ``` cpp
537
  template<class U1, class U2> constexpr tuple& operator=(pair<U1, U2>&& u);
538
  ```
539
 
540
  *Constraints:*
 
547
  `*this` and
548
  `std::forward<U2>(u.second)` to the second element of `*this`.
549
 
550
  *Returns:* `*this`.
551
 
552
+ ``` cpp
553
+ template<class U1, class U2> constexpr const tuple& operator=(pair<U1, U2>&& u) const;
554
+ ```
555
+
556
+ *Constraints:*
557
+
558
+ - `sizeof...(Types)` is 2,
559
+ - `is_assignable_v<const ``T₀``&, U1>` is `true`, and
560
+ - `is_assignable_v<const ``T₁``&, U2>` is `true`.
561
+
562
+ *Effects:* Assigns `std::forward<U1>(u.first)` to the first element
563
+ and
564
+ `std::forward<U2>(u.second)` to the second element.
565
+
566
+ *Returns:* `*this`.
567
+
568
+ ``` cpp
569
+ template<tuple-like UTuple>
570
+ constexpr tuple& operator=(UTuple&& u);
571
+ ```
572
+
573
+ *Constraints:*
574
+
575
+ - `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
576
+ - `remove_cvref_t<UTuple>` is not a specialization of
577
+ `ranges::subrange`,
578
+ - `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`, and,
579
+ - `is_assignable_v<``Tᵢ``&, decltype(get<`i`>(std::forward<UTuple>(u)))>`
580
+ is `true` for all i.
581
+
582
+ *Effects:* For all i, assigns `get<`i`>(std::forward<UTuple>(u))` to
583
+ `get<`i`>(*this)`.
584
+
585
+ *Returns:* `*this`.
586
+
587
+ ``` cpp
588
+ template<tuple-like UTuple>
589
+ constexpr const tuple& operator=(UTuple&& u) const;
590
+ ```
591
+
592
+ *Constraints:*
593
+
594
+ - `different-from<UTuple, tuple>` [[range.utility.helpers]] is `true`,
595
+ - `remove_cvref_t<UTuple>` is not a specialization of
596
+ `ranges::subrange`,
597
+ - `sizeof...(Types)` equals `tuple_size_v<remove_cvref_t<UTuple>>`, and,
598
+ - `is_assignable_v<const ``Tᵢ``&, decltype(get<`i`>(std::forward<UTuple>(u)))>`
599
+ is `true` for all i.
600
+
601
+ *Effects:* For all i, assigns `get<`i`>(std::forward<UTuple>(u))` to
602
+ `get<`i`>(*this)`.
603
+
604
+ *Returns:* `*this`.
605
+
606
  #### `swap` <a id="tuple.swap">[[tuple.swap]]</a>
607
 
608
  ``` cpp
609
  constexpr void swap(tuple& rhs) noexcept(see below);
610
+ constexpr void swap(const tuple& rhs) const noexcept(see below);
611
  ```
612
 
613
+ Let i be in the range \[`0`, `sizeof...(Types)`) in order.
 
614
 
615
+ *Mandates:*
 
616
 
617
+ - For the first overload, `(is_swappable_v<Types> && ...)` is `true`.
618
+ - For the second overload, `(is_swappable_v<const Types> && ...)` is
619
+ `true`.
620
 
621
+ *Preconditions:* For all i, `get<`i`>(*this)` is swappable
622
+ with [[swappable.requirements]] `get<`i`>(rhs)`.
 
623
 
624
+ *Effects:* For each i, calls `swap` for `get<`i`>(*this)` with
625
+ `get<`i`>(rhs)`.
626
 
627
  *Throws:* Nothing unless one of the element-wise `swap` calls throws an
628
  exception.
629
 
630
+ *Remarks:* The exception specification is equivalent to
631
+
632
+ - `(is_nothrow_swappable_v<Types> && ...)` for the first overload and
633
+ - `(is_nothrow_swappable_v<const Types> && ...)` for the second
634
+ overload.
635
+