From Jason Turner

[pairs]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpz1ul3z1w/{from.md → to.md} +197 -66
tmp/tmpz1ul3z1w/{from.md → to.md} RENAMED
@@ -22,28 +22,45 @@ namespace std {
22
 
23
  pair(const pair&) = default;
24
  pair(pair&&) = default;
25
  constexpr explicit(see below) pair();
26
  constexpr explicit(see below) pair(const T1& x, const T2& y);
27
- template<class U1, class U2>
28
  constexpr explicit(see below) pair(U1&& x, U2&& y);
 
 
29
  template<class U1, class U2>
30
  constexpr explicit(see below) pair(const pair<U1, U2>& p);
31
  template<class U1, class U2>
32
  constexpr explicit(see below) pair(pair<U1, U2>&& p);
 
 
 
 
33
  template<class... Args1, class... Args2>
34
  constexpr pair(piecewise_construct_t,
35
  tuple<Args1...> first_args, tuple<Args2...> second_args);
36
 
37
  constexpr pair& operator=(const pair& p);
 
38
  template<class U1, class U2>
39
  constexpr pair& operator=(const pair<U1, U2>& p);
 
 
40
  constexpr pair& operator=(pair&& p) noexcept(see below);
 
41
  template<class U1, class U2>
42
  constexpr pair& operator=(pair<U1, U2>&& p);
 
 
 
 
 
 
43
 
44
  constexpr void swap(pair& p) noexcept(see below);
 
45
  };
46
 
47
  template<class T1, class T2>
48
  pair(T1, T2) -> pair<T1, T2>;
49
  }
@@ -53,12 +70,12 @@ Constructors and member functions of `pair` do not throw exceptions
53
  unless one of the element-wise operations specified to be called for
54
  that operation throws an exception.
55
 
56
  The defaulted move and copy constructor, respectively, of `pair` is a
57
  constexpr function if and only if all required element-wise
58
- initializations for move and copy, respectively, would satisfy the
59
- requirements for a constexpr function.
60
 
61
  If
62
  `(is_trivially_destructible_v<T1> && is_trivially_destructible_v<T2>)`
63
  is `true`, then the destructor of `pair` is trivial.
64
 
@@ -72,135 +89,168 @@ template-argument-equivalent [[temp.type]] if and only if `p1.first` and
72
  constexpr explicit(see below) pair();
73
  ```
74
 
75
  *Constraints:*
76
 
77
- - `is_default_constructible_v<first_type>` is `true` and
78
- - `is_default_constructible_v<second_type>` is `true`.
79
 
80
  *Effects:* Value-initializes `first` and `second`.
81
 
82
  *Remarks:* The expression inside `explicit` evaluates to `true` if and
83
- only if either `first_type` or `second_type` is not implicitly
84
- default-constructible.
85
 
86
  [*Note 1*: This behavior can be implemented with a trait that checks
87
- whether a `const first_type&` or a `const second_type&` can be
88
- initialized with `{}`. — *end note*]
89
 
90
  ``` cpp
91
  constexpr explicit(see below) pair(const T1& x, const T2& y);
92
  ```
93
 
94
  *Constraints:*
95
 
96
- - `is_copy_constructible_v<first_type>` is `true` and
97
- - `is_copy_constructible_v<second_type>` is `true`.
98
 
99
  *Effects:* Initializes `first` with `x` and `second` with `y`.
100
 
101
  *Remarks:* The expression inside `explicit` is equivalent to:
102
 
103
  ``` cpp
104
- !is_convertible_v<const first_type&, first_type> ||
105
- !is_convertible_v<const second_type&, second_type>
106
  ```
107
 
108
  ``` cpp
109
- template<class U1, class U2> constexpr explicit(see below) pair(U1&& x, U2&& y);
110
  ```
111
 
112
  *Constraints:*
113
 
114
- - `is_constructible_v<first_type, U1>` is `true` and
115
- - `is_constructible_v<second_type, U2>` is `true`.
116
 
117
  *Effects:* Initializes `first` with `std::forward<U1>(x)` and `second`
118
  with `std::forward<U2>(y)`.
119
 
120
  *Remarks:* The expression inside `explicit` is equivalent to:
121
 
122
  ``` cpp
123
- !is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
124
  ```
125
 
 
 
 
 
126
  ``` cpp
 
127
  template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p);
128
- ```
129
-
130
- *Constraints:*
131
-
132
- - `is_constructible_v<first_type, const U1&>` is `true` and
133
- - `is_constructible_v<second_type, const U2&>` is `true`.
134
-
135
- *Effects:* Initializes members from the corresponding members of the
136
- argument.
137
-
138
- *Remarks:* The expression inside explicit is equivalent to:
139
-
140
- ``` cpp
141
- !is_convertible_v<const U1&, first_type> || !is_convertible_v<const U2&, second_type>
142
- ```
143
-
144
- ``` cpp
145
  template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p);
 
 
146
  ```
147
 
 
 
148
  *Constraints:*
149
 
150
- - `is_constructible_v<first_type, U1>` is `true` and
151
- - `is_constructible_v<second_type, U2>` is `true`.
 
 
 
152
 
153
- *Effects:* Initializes `first` with `std::forward<U1>(p.first)` and
154
- `second` with `std::forward<U2>(p.second)`.
155
 
156
- *Remarks:* The expression inside explicit is equivalent to:
157
 
158
  ``` cpp
159
- !is_convertible_v<U1, first_type> || !is_convertible_v<U2, second_type>
 
160
  ```
161
 
 
 
 
 
 
 
 
 
 
162
  ``` cpp
163
  template<class... Args1, class... Args2>
164
  constexpr pair(piecewise_construct_t,
165
  tuple<Args1...> first_args, tuple<Args2...> second_args);
166
  ```
167
 
168
  *Mandates:*
169
 
170
- - `is_constructible_v<first_type, Args1...>` is `true` and
171
- - `is_constructible_v<second_type, Args2...>` is `true`.
172
 
173
  *Effects:* Initializes `first` with arguments of types `Args1...`
174
  obtained by forwarding the elements of `first_args` and initializes
175
  `second` with arguments of types `Args2...` obtained by forwarding the
176
  elements of `second_args`. (Here, forwarding an element `x` of type `U`
177
  within a `tuple` object means calling `std::forward<U>(x)`.) This form
178
  of construction, whereby constructor arguments for `first` and `second`
179
  are each provided in a separate `tuple` object, is called *piecewise
180
  construction*.
181
 
 
 
 
 
182
  ``` cpp
183
  constexpr pair& operator=(const pair& p);
184
  ```
185
 
186
  *Effects:* Assigns `p.first` to `first` and `p.second` to `second`.
187
 
 
 
188
  *Remarks:* This operator is defined as deleted unless
189
- `is_copy_assignable_v<first_type>` is `true` and
190
- `is_copy_assignable_v<second_type>` is `true`.
 
 
 
 
 
 
 
 
 
 
 
191
 
192
  *Returns:* `*this`.
193
 
194
  ``` cpp
195
  template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p);
196
  ```
197
 
198
  *Constraints:*
199
 
200
- - `is_assignable_v<first_type&, const U1&>` is `true` and
201
- - `is_assignable_v<second_type&, const U2&>` is `true`.
 
 
 
 
 
 
 
 
 
 
 
 
 
202
 
203
  *Effects:* Assigns `p.first` to `first` and `p.second` to `second`.
204
 
205
  *Returns:* `*this`.
206
 
@@ -208,69 +258,144 @@ template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p);
208
  constexpr pair& operator=(pair&& p) noexcept(see below);
209
  ```
210
 
211
  *Constraints:*
212
 
213
- - `is_move_assignable_v<first_type>` is `true` and
214
- - `is_move_assignable_v<second_type>` is `true`.
215
 
216
- *Effects:* Assigns to `first` with `std::forward<first_type>(p.first)`
217
- and to `second` with
218
- `std::forward<second_type>(p.second)`.
219
 
220
  *Returns:* `*this`.
221
 
222
- *Remarks:* The expression inside `noexcept` is equivalent to:
223
 
224
  ``` cpp
225
  is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
226
  ```
227
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  ``` cpp
229
  template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p);
230
  ```
231
 
232
  *Constraints:*
233
 
234
- - `is_assignable_v<first_type&, U1>` is `true` and
235
- - `is_assignable_v<second_type&, U2>` is `true`.
236
 
237
  *Effects:* Assigns to `first` with `std::forward<U1>(p.first)` and to
238
  `second` with
239
  `std::forward<U2>(p.second)`.
240
 
241
  *Returns:* `*this`.
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  ``` cpp
244
  constexpr void swap(pair& p) noexcept(see below);
 
245
  ```
246
 
 
 
 
 
 
 
 
247
  *Preconditions:* `first` is swappable with [[swappable.requirements]]
248
  `p.first` and `second` is swappable with `p.second`.
249
 
250
  *Effects:* Swaps `first` with `p.first` and `second` with `p.second`.
251
 
252
- *Remarks:* The expression inside `noexcept` is equivalent to:
253
 
254
- ``` cpp
255
- is_nothrow_swappable_v<first_type> && is_nothrow_swappable_v<second_type>
256
- ```
 
257
 
258
  ### Specialized algorithms <a id="pairs.spec">[[pairs.spec]]</a>
259
 
260
  ``` cpp
261
- template<class T1, class T2>
262
- constexpr bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y);
263
  ```
264
 
 
 
 
265
  *Returns:* `x.first == y.first && x.second == y.second`.
266
 
267
  ``` cpp
268
- template<class T1, class T2>
269
- constexpr common_comparison_category_t<synth-three-way-result<T1>,
270
- synth-three-way-result<T2>>
271
- operator<=>(const pair<T1, T2>& x, const pair<T1, T2>& y);
272
  ```
273
 
274
  *Effects:* Equivalent to:
275
 
276
  ``` cpp
@@ -279,14 +404,20 @@ return synth-three-way(x.second, y.second);
279
  ```
280
 
281
  ``` cpp
282
  template<class T1, class T2>
283
  constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
 
 
284
  ```
285
 
286
- *Constraints:* `is_swappable_v<T1>` is `true` and `is_swappable_v<T2>`
287
- is `true`.
 
 
 
 
288
 
289
  *Effects:* Equivalent to `x.swap(y)`.
290
 
291
  ``` cpp
292
  template<class T1, class T2>
 
22
 
23
  pair(const pair&) = default;
24
  pair(pair&&) = default;
25
  constexpr explicit(see below) pair();
26
  constexpr explicit(see below) pair(const T1& x, const T2& y);
27
+ template<class U1 = T1, class U2 = T2>
28
  constexpr explicit(see below) pair(U1&& x, U2&& y);
29
+ template<class U1, class U2>
30
+ constexpr explicit(see below) pair(pair<U1, U2>& p);
31
  template<class U1, class U2>
32
  constexpr explicit(see below) pair(const pair<U1, U2>& p);
33
  template<class U1, class U2>
34
  constexpr explicit(see below) pair(pair<U1, U2>&& p);
35
+ template<class U1, class U2>
36
+ constexpr explicit(see below) pair(const pair<U1, U2>&& p);
37
+ template<pair-like P>
38
+ constexpr explicit(see below) pair(P&& p);
39
  template<class... Args1, class... Args2>
40
  constexpr pair(piecewise_construct_t,
41
  tuple<Args1...> first_args, tuple<Args2...> second_args);
42
 
43
  constexpr pair& operator=(const pair& p);
44
+ constexpr const pair& operator=(const pair& p) const;
45
  template<class U1, class U2>
46
  constexpr pair& operator=(const pair<U1, U2>& p);
47
+ template<class U1, class U2>
48
+ constexpr const pair& operator=(const pair<U1, U2>& p) const;
49
  constexpr pair& operator=(pair&& p) noexcept(see below);
50
+ constexpr const pair& operator=(pair&& p) const;
51
  template<class U1, class U2>
52
  constexpr pair& operator=(pair<U1, U2>&& p);
53
+ template<class U1, class U2>
54
+ constexpr const pair& operator=(pair<U1, U2>&& p) const;
55
+ template<pair-like P>
56
+ constexpr pair& operator=(P&& p);
57
+ template<pair-like P>
58
+ constexpr const pair& operator=(P&& p) const;
59
 
60
  constexpr void swap(pair& p) noexcept(see below);
61
+ constexpr void swap(const pair& p) const noexcept(see below);
62
  };
63
 
64
  template<class T1, class T2>
65
  pair(T1, T2) -> pair<T1, T2>;
66
  }
 
70
  unless one of the element-wise operations specified to be called for
71
  that operation throws an exception.
72
 
73
  The defaulted move and copy constructor, respectively, of `pair` is a
74
  constexpr function if and only if all required element-wise
75
+ initializations for move and copy, respectively, would be
76
+ constexpr-suitable [[dcl.constexpr]].
77
 
78
  If
79
  `(is_trivially_destructible_v<T1> && is_trivially_destructible_v<T2>)`
80
  is `true`, then the destructor of `pair` is trivial.
81
 
 
89
  constexpr explicit(see below) pair();
90
  ```
91
 
92
  *Constraints:*
93
 
94
+ - `is_default_constructible_v<T1>` is `true` and
95
+ - `is_default_constructible_v<T2>` is `true`.
96
 
97
  *Effects:* Value-initializes `first` and `second`.
98
 
99
  *Remarks:* The expression inside `explicit` evaluates to `true` if and
100
+ only if either `T1` or `T2` is not implicitly default-constructible.
 
101
 
102
  [*Note 1*: This behavior can be implemented with a trait that checks
103
+ whether a `const T1&` or a `const T2&` can be initialized with
104
+ `{}`. — *end note*]
105
 
106
  ``` cpp
107
  constexpr explicit(see below) pair(const T1& x, const T2& y);
108
  ```
109
 
110
  *Constraints:*
111
 
112
+ - `is_copy_constructible_v<T1>` is `true` and
113
+ - `is_copy_constructible_v<T2>` is `true`.
114
 
115
  *Effects:* Initializes `first` with `x` and `second` with `y`.
116
 
117
  *Remarks:* The expression inside `explicit` is equivalent to:
118
 
119
  ``` cpp
120
+ !is_convertible_v<const T1&, T1> || !is_convertible_v<const T2&, T2>
 
121
  ```
122
 
123
  ``` cpp
124
+ template<class U1 = T1, class U2 = T2> constexpr explicit(see below) pair(U1&& x, U2&& y);
125
  ```
126
 
127
  *Constraints:*
128
 
129
+ - `is_constructible_v<T1, U1>` is `true` and
130
+ - `is_constructible_v<T2, U2>` is `true`.
131
 
132
  *Effects:* Initializes `first` with `std::forward<U1>(x)` and `second`
133
  with `std::forward<U2>(y)`.
134
 
135
  *Remarks:* The expression inside `explicit` is equivalent to:
136
 
137
  ``` cpp
138
+ !is_convertible_v<U1, T1> || !is_convertible_v<U2, T2>
139
  ```
140
 
141
+ This constructor is defined as deleted if
142
+ `reference_constructs_from_temporary_v<first_type, U1&&>` is `true` or
143
+ `reference_constructs_from_temporary_v<second_type, U2&&>` is `true`.
144
+
145
  ``` cpp
146
+ template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>& p);
147
  template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>& p);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  template<class U1, class U2> constexpr explicit(see below) pair(pair<U1, U2>&& p);
149
+ template<class U1, class U2> constexpr explicit(see below) pair(const pair<U1, U2>&& p);
150
+ template<pair-like P> constexpr explicit(see below) pair(P&& p);
151
  ```
152
 
153
+ Let *`FWD`*`(u)` be `static_cast<decltype(u)>(u)`.
154
+
155
  *Constraints:*
156
 
157
+ - For the last overload, `remove_cvref_t<P>` is not a specialization of
158
+ `ranges::subrange`,
159
+ - `is_constructible_v<T1, decltype(get<0>(`*`FWD`*`(p)))>` is `true`,
160
+ and
161
+ - `is_constructible_v<T2, decltype(get<1>(`*`FWD`*`(p)))>` is `true`.
162
 
163
+ *Effects:* Initializes `first` with `get<0>(`*`FWD`*`(p))` and `second`
164
+ with `get<1>(`*`FWD`*`(p))`.
165
 
166
+ *Remarks:* The expression inside `explicit` is equivalent to:
167
 
168
  ``` cpp
169
+ !is_convertible_v<decltype(get<0>(FWD(p))), T1> ||
170
+ !is_convertible_v<decltype(get<1>(FWD(p))), T2>
171
  ```
172
 
173
+ The constructor is defined as deleted if
174
+
175
+ ``` cpp
176
+ reference_constructs_from_temporary_v<first_type, decltype(get<0>(FWD(p)))> ||
177
+ reference_constructs_from_temporary_v<second_type, decltype(get<1>(FWD(p)))>
178
+ ```
179
+
180
+ is `true`.
181
+
182
  ``` cpp
183
  template<class... Args1, class... Args2>
184
  constexpr pair(piecewise_construct_t,
185
  tuple<Args1...> first_args, tuple<Args2...> second_args);
186
  ```
187
 
188
  *Mandates:*
189
 
190
+ - `is_constructible_v<T1, Args1...>` is `true` and
191
+ - `is_constructible_v<T2, Args2...>` is `true`.
192
 
193
  *Effects:* Initializes `first` with arguments of types `Args1...`
194
  obtained by forwarding the elements of `first_args` and initializes
195
  `second` with arguments of types `Args2...` obtained by forwarding the
196
  elements of `second_args`. (Here, forwarding an element `x` of type `U`
197
  within a `tuple` object means calling `std::forward<U>(x)`.) This form
198
  of construction, whereby constructor arguments for `first` and `second`
199
  are each provided in a separate `tuple` object, is called *piecewise
200
  construction*.
201
 
202
+ [*Note 2*: If a data member of `pair` is of reference type and its
203
+ initialization binds it to a temporary object, the program is
204
+ ill-formed [[class.base.init]]. — *end note*]
205
+
206
  ``` cpp
207
  constexpr pair& operator=(const pair& p);
208
  ```
209
 
210
  *Effects:* Assigns `p.first` to `first` and `p.second` to `second`.
211
 
212
+ *Returns:* `*this`.
213
+
214
  *Remarks:* This operator is defined as deleted unless
215
+ `is_copy_assignable_v<T1>` is `true` and `is_copy_assignable_v<T2>` is
216
+ `true`.
217
+
218
+ ``` cpp
219
+ constexpr const pair& operator=(const pair& p) const;
220
+ ```
221
+
222
+ *Constraints:*
223
+
224
+ - `is_copy_assignable_v<const T1>` is `true` and
225
+ - `is_copy_assignable_v<const T2>` is `true`.
226
+
227
+ *Effects:* Assigns `p.first` to `first` and `p.second` to `second`.
228
 
229
  *Returns:* `*this`.
230
 
231
  ``` cpp
232
  template<class U1, class U2> constexpr pair& operator=(const pair<U1, U2>& p);
233
  ```
234
 
235
  *Constraints:*
236
 
237
+ - `is_assignable_v<T1&, const U1&>` is `true` and
238
+ - `is_assignable_v<T2&, const U2&>` is `true`.
239
+
240
+ *Effects:* Assigns `p.first` to `first` and `p.second` to `second`.
241
+
242
+ *Returns:* `*this`.
243
+
244
+ ``` cpp
245
+ template<class U1, class U2> constexpr const pair& operator=(const pair<U1, U2>& p) const;
246
+ ```
247
+
248
+ *Constraints:*
249
+
250
+ - `is_assignable_v<const T1&, const U1&>` is `true`, and
251
+ - `is_assignable_v<const T2&, const U2&>` is `true`.
252
 
253
  *Effects:* Assigns `p.first` to `first` and `p.second` to `second`.
254
 
255
  *Returns:* `*this`.
256
 
 
258
  constexpr pair& operator=(pair&& p) noexcept(see below);
259
  ```
260
 
261
  *Constraints:*
262
 
263
+ - `is_move_assignable_v<T1>` is `true` and
264
+ - `is_move_assignable_v<T2>` is `true`.
265
 
266
+ *Effects:* Assigns to `first` with `std::forward<T1>(p.first)` and to
267
+ `second` with `std::forward<T2>(p.second)`.
 
268
 
269
  *Returns:* `*this`.
270
 
271
+ *Remarks:* The exception specification is equivalent to:
272
 
273
  ``` cpp
274
  is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
275
  ```
276
 
277
+ ``` cpp
278
+ constexpr const pair& operator=(pair&& p) const;
279
+ ```
280
+
281
+ *Constraints:*
282
+
283
+ - `is_assignable_v<const T1&, T1>` is `true` and
284
+ - `is_assignable_v<const T2&, T2>` is `true`.
285
+
286
+ *Effects:* Assigns `std::forward<T1>(p.first)` to `first` and
287
+ `std::forward<T2>(p.second)` to `second`.
288
+
289
+ *Returns:* `*this`.
290
+
291
  ``` cpp
292
  template<class U1, class U2> constexpr pair& operator=(pair<U1, U2>&& p);
293
  ```
294
 
295
  *Constraints:*
296
 
297
+ - `is_assignable_v<T1&, U1>` is `true` and
298
+ - `is_assignable_v<T2&, U2>` is `true`.
299
 
300
  *Effects:* Assigns to `first` with `std::forward<U1>(p.first)` and to
301
  `second` with
302
  `std::forward<U2>(p.second)`.
303
 
304
  *Returns:* `*this`.
305
 
306
+ ``` cpp
307
+ template<pair-like P> constexpr pair& operator=(P&& p);
308
+ ```
309
+
310
+ *Constraints:*
311
+
312
+ - `different-from<P, pair>` [[range.utility.helpers]] is `true`,
313
+ - `remove_cvref_t<P>` is not a specialization of `ranges::subrange`,
314
+ - `is_assignable_v<T1&, decltype(get<0>(std::forward<P>(p)))>` is
315
+ `true`, and
316
+ - `is_assignable_v<T2&, decltype(get<1>(std::forward<P>(p)))>` is
317
+ `true`.
318
+
319
+ *Effects:* Assigns `get<0>(std::forward<P>(p))` to `first` and
320
+ `get<1>(std::forward<P>(p))` to `second`.
321
+
322
+ *Returns:* `*this`.
323
+
324
+ ``` cpp
325
+ template<pair-like P> constexpr const pair& operator=(P&& p) const;
326
+ ```
327
+
328
+ *Constraints:*
329
+
330
+ - `different-from<P, pair>` [[range.utility.helpers]] is `true`,
331
+ - `remove_cvref_t<P>` is not a specialization of `ranges::subrange`,
332
+ - `is_assignable_v<const T1&, decltype(get<0>(std::forward<P>(p)))>` is
333
+ `true`, and
334
+ - `is_assignable_v<const T2&, decltype(get<1>(std::forward<P>(p)))>` is
335
+ `true`.
336
+
337
+ *Effects:* Assigns `get<0>(std::forward<P>(p))` to `first` and
338
+ `get<1>(std::forward<P>(p))` to `second`.
339
+
340
+ *Returns:* `*this`.
341
+
342
+ ``` cpp
343
+ template<class U1, class U2> constexpr const pair& operator=(pair<U1, U2>&& p) const;
344
+ ```
345
+
346
+ *Constraints:*
347
+
348
+ - `is_assignable_v<const T1&, U1>` is `true`, and
349
+ - `is_assignable_v<const T2&, U2>` is `true`.
350
+
351
+ *Effects:* Assigns `std::forward<U1>(p.first)` to `first` and
352
+ `std::forward<U2>(u.second)` to `second`.
353
+
354
+ *Returns:* `*this`.
355
+
356
  ``` cpp
357
  constexpr void swap(pair& p) noexcept(see below);
358
+ constexpr void swap(const pair& p) const noexcept(see below);
359
  ```
360
 
361
+ *Mandates:*
362
+
363
+ - For the first overload, `is_swappable_v<T1>` is `true` and
364
+ `is_swappable_v<T2>` is `true`.
365
+ - For the second overload, `is_swappable_v<const T1>` is `true` and
366
+ `is_swappable_v<const T2>` is `true`.
367
+
368
  *Preconditions:* `first` is swappable with [[swappable.requirements]]
369
  `p.first` and `second` is swappable with `p.second`.
370
 
371
  *Effects:* Swaps `first` with `p.first` and `second` with `p.second`.
372
 
373
+ *Remarks:* The exception specification is equivalent to:
374
 
375
+ - `is_nothrow_swappable_v<T1> && is_nothrow_swappable_v<T2>` for the
376
+ first overload, and
377
+ - `is_nothrow_swappable_v<const T1> && is_nothrow_swappable_v<const T2>`
378
+ for the second overload.
379
 
380
  ### Specialized algorithms <a id="pairs.spec">[[pairs.spec]]</a>
381
 
382
  ``` cpp
383
+ template<class T1, class T2, class U1, class U2>
384
+ constexpr bool operator==(const pair<T1, T2>& x, const pair<U1, U2>& y);
385
  ```
386
 
387
+ *Preconditions:* Each of `decltype(x.first == y.first)` and
388
+ `decltype(x.second == y.second)` models `boolean-testable`.
389
+
390
  *Returns:* `x.first == y.first && x.second == y.second`.
391
 
392
  ``` cpp
393
+ template<class T1, class T2, class U1, class U2>
394
+ constexpr common_comparison_category_t<synth-three-way-result<T1, U1>,
395
+ synth-three-way-result<T2, U2>>
396
+ operator<=>(const pair<T1, T2>& x, const pair<U1, U2>& y);
397
  ```
398
 
399
  *Effects:* Equivalent to:
400
 
401
  ``` cpp
 
404
  ```
405
 
406
  ``` cpp
407
  template<class T1, class T2>
408
  constexpr void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
409
+ template<class T1, class T2>
410
+ constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));
411
  ```
412
 
413
+ *Constraints:*
414
+
415
+ - For the first overload, `is_swappable_v<T1>` is `true` and
416
+ `is_swappable_v<T2>` is `true`.
417
+ - For the second overload, `is_swappable_v<const T1>` is `true` and
418
+ `is_swappable_v<const T2>` is `true`.
419
 
420
  *Effects:* Equivalent to `x.swap(y)`.
421
 
422
  ``` cpp
423
  template<class T1, class T2>