From Jason Turner

[indirect]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp17mghs_y/{from.md → to.md} +531 -0
tmp/tmp17mghs_y/{from.md → to.md} RENAMED
@@ -0,0 +1,531 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Class template `indirect` <a id="indirect">[[indirect]]</a>
2
+
3
+ #### General <a id="indirect.general">[[indirect.general]]</a>
4
+
5
+ An indirect object manages the lifetime of an owned object. An indirect
6
+ object is *valueless* if it has no owned object. An indirect object may
7
+ become valueless only after it has been moved from.
8
+
9
+ In every specialization `indirect<T, Allocator>`, if the type
10
+ `allocator_traits<Allocator>::value_type` is not the same type as `T`,
11
+ the program is ill-formed. Every object of type `indirect<T, Allocator>`
12
+ uses an object of type `Allocator` to allocate and free storage for the
13
+ owned object as needed.
14
+
15
+ Constructing an owned object with `args...` using the allocator `a`
16
+ means calling `allocator_traits<Allocator>::construct(a, p, args...)`
17
+ where `args` is an expression pack, `a` is an allocator, and *`p`* is a
18
+ pointer obtained by calling `allocator_traits<Allocator>::allocate`.
19
+
20
+ The member *`alloc`* is used for any memory allocation and element
21
+ construction performed by member functions during the lifetime of each
22
+ indirect object. The allocator *`alloc`* may be replaced only via
23
+ assignment or `swap()`. `Allocator` replacement is performed by copy
24
+ assignment, move assignment, or swapping of the allocator only if
25
+ [[container.reqmts]]:
26
+
27
+ - `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value`,
28
+ or
29
+ - `allocator_traits<Allocator>::propagate_on_container_move_assignment::value`,
30
+ or
31
+ - `allocator_traits<Allocator>::propagate_on_container_swap::value`
32
+
33
+ is `true` within the implementation of the corresponding `indirect`
34
+ operation.
35
+
36
+ A program that instantiates the definition of the template
37
+ `indirect<T, Allocator>` with a type for the `T` parameter that is a
38
+ non-object type, an array type, `in_place_t`, a specialization of
39
+ `in_place_type_t`, or a cv-qualified type is ill-formed.
40
+
41
+ The template parameter `T` of `indirect` may be an incomplete type.
42
+
43
+ The template parameter `Allocator` of `indirect` shall meet the
44
+ *Cpp17Allocator* requirements.
45
+
46
+ If a program declares an explicit or partial specialization of
47
+ `indirect`, the behavior is undefined.
48
+
49
+ #### Synopsis <a id="indirect.syn">[[indirect.syn]]</a>
50
+
51
+ ``` cpp
52
+ namespace std {
53
+ template<class T, class Allocator = allocator<T>>
54
+ class indirect {
55
+ public:
56
+ using value_type = T;
57
+ using allocator_type = Allocator;
58
+ using pointer = allocator_traits<Allocator>::pointer;
59
+ using const_pointer = allocator_traits<Allocator>::const_pointer;
60
+
61
+ // [indirect.ctor], constructors
62
+ constexpr explicit indirect();
63
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a);
64
+ constexpr indirect(const indirect& other);
65
+ constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other);
66
+ constexpr indirect(indirect&& other) noexcept;
67
+ constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other)
68
+ noexcept(see below);
69
+ template<class U = T>
70
+ constexpr explicit indirect(U&& u);
71
+ template<class U = T>
72
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u);
73
+ template<class... Us>
74
+ constexpr explicit indirect(in_place_t, Us&&... us);
75
+ template<class... Us>
76
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a,
77
+ in_place_t, Us&&... us);
78
+ template<class I, class... Us>
79
+ constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us);
80
+ template<class I, class... Us>
81
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a,
82
+ in_place_t, initializer_list<I> ilist, Us&&... us);
83
+
84
+ // [indirect.dtor], destructor
85
+ constexpr ~indirect();
86
+
87
+ // [indirect.assign], assignment
88
+ constexpr indirect& operator=(const indirect& other);
89
+ constexpr indirect& operator=(indirect&& other) noexcept(see below);
90
+ template<class U = T>
91
+ constexpr indirect& operator=(U&& u);
92
+
93
+ // [indirect.obs], observers
94
+ constexpr const T& operator*() const & noexcept;
95
+ constexpr T& operator*() & noexcept;
96
+ constexpr const T&& operator*() const && noexcept;
97
+ constexpr T&& operator*() && noexcept;
98
+ constexpr const_pointer operator->() const noexcept;
99
+ constexpr pointer operator->() noexcept;
100
+ constexpr bool valueless_after_move() const noexcept;
101
+ constexpr allocator_type get_allocator() const noexcept;
102
+
103
+ // [indirect.swap], swap
104
+ constexpr void swap(indirect& other) noexcept(see below);
105
+ friend constexpr void swap(indirect& lhs, indirect& rhs) noexcept(see below);
106
+
107
+ // [indirect.relops], relational operators
108
+ template<class U, class AA>
109
+ friend constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs)
110
+ noexcept(see below);
111
+ template<class U, class AA>
112
+ friend constexpr auto operator<=>(const indirect& lhs, const indirect<U, AA>& rhs)
113
+ -> synth-three-way-result<T, U>;
114
+
115
+ // [indirect.comp.with.t], comparison with T
116
+ template<class U>
117
+ friend constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(see below);
118
+ template<class U>
119
+ friend constexpr auto operator<=>(const indirect& lhs, const U& rhs)
120
+ -> synth-three-way-result<T, U>;
121
+
122
+ private:
123
+ pointer p; // exposition only
124
+ Allocator alloc = Allocator(); // exposition only
125
+ };
126
+ template<class Value>
127
+ indirect(Value) -> indirect<Value>;
128
+ template<class Allocator, class Value>
129
+ indirect(allocator_arg_t, Allocator, Value)
130
+ -> indirect<Value, typename allocator_traits<Allocator>::template rebind_alloc<Value>>;
131
+ }
132
+ ```
133
+
134
+ #### Constructors <a id="indirect.ctor">[[indirect.ctor]]</a>
135
+
136
+ The following element applies to all functions in  [[indirect.ctor]]:
137
+
138
+ *Throws:* Nothing unless `allocator_traits<Allocator>::allocate` or
139
+ `allocator_traits<Allocator>::construct` throws.
140
+
141
+ ``` cpp
142
+ constexpr explicit indirect();
143
+ ```
144
+
145
+ *Constraints:* `is_default_constructible_v<Allocator>` is `true`.
146
+
147
+ *Mandates:* `is_default_constructible_v<T>` is `true`.
148
+
149
+ *Effects:* Constructs an owned object of type `T` with an empty argument
150
+ list, using the allocator *alloc*.
151
+
152
+ ``` cpp
153
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a);
154
+ ```
155
+
156
+ *Mandates:* `is_default_constructible_v<T>` is `true`.
157
+
158
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
159
+ an owned object of type `T` with an empty argument list, using the
160
+ allocator *alloc*.
161
+
162
+ ``` cpp
163
+ constexpr indirect(const indirect& other);
164
+ ```
165
+
166
+ *Mandates:* `is_copy_constructible_v<T>` is `true`.
167
+
168
+ *Effects:* *alloc* is direct-non-list-initialized with
169
+ `allocator_traits<Allocator>::select_on_container_copy_construction(other.`*`alloc`*`)`.
170
+ If `other` is valueless, `*this` is valueless. Otherwise, constructs an
171
+ owned object of type `T` with `*other`, using the allocator *alloc*.
172
+
173
+ ``` cpp
174
+ constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other);
175
+ ```
176
+
177
+ *Mandates:* `is_copy_constructible_v<T>` is `true`.
178
+
179
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. If `other`
180
+ is valueless, `*this` is valueless. Otherwise, constructs an owned
181
+ object of type `T` with `*other`, using the allocator *alloc*.
182
+
183
+ ``` cpp
184
+ constexpr indirect(indirect&& other) noexcept;
185
+ ```
186
+
187
+ *Effects:* *alloc* is direct-non-list-initialized from
188
+ `std::move(other.`*`alloc`*`)`. If `other` is valueless, `*this` is
189
+ valueless. Otherwise `*this` takes ownership of the owned object of
190
+ `other`.
191
+
192
+ *Ensures:* `other` is valueless.
193
+
194
+ ``` cpp
195
+ constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other)
196
+ noexcept(allocator_traits<Allocator>::is_always_equal::value);
197
+ ```
198
+
199
+ *Mandates:* If `allocator_traits<Allocator>::is_always_equal::value` is
200
+ `false` then `T` is a complete type.
201
+
202
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. If `other`
203
+ is valueless, `*this` is valueless. Otherwise, if
204
+ *`alloc`*` == other.`*`alloc`* is `true`, constructs an object of type
205
+ `indirect` that takes ownership of the owned object of `other`.
206
+ Otherwise, constructs an owned object of type `T` with
207
+ `*std::move(other)`, using the allocator *alloc*.
208
+
209
+ *Ensures:* `other` is valueless.
210
+
211
+ ``` cpp
212
+ template<class U = T>
213
+ constexpr explicit indirect(U&& u);
214
+ ```
215
+
216
+ *Constraints:*
217
+
218
+ - `is_same_v<remove_cvref_t<U>, indirect>` is `false`,
219
+ - `is_same_v<remove_cvref_t<U>, in_place_t>` is `false`,
220
+ - `is_constructible_v<T, U>` is `true`, and
221
+ - `is_default_constructible_v<Allocator>` is `true`.
222
+
223
+ *Effects:* Constructs an owned object of type `T` with
224
+ `std::forward<U>(u)`, using the allocator *alloc*.
225
+
226
+ ``` cpp
227
+ template<class U = T>
228
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u);
229
+ ```
230
+
231
+ *Constraints:*
232
+
233
+ - `is_same_v<remove_cvref_t<U>, indirect>` is `false`,
234
+ - `is_same_v<remove_cvref_t<U>, in_place_t>` is `false`, and
235
+ - `is_constructible_v<T, U>` is `true`.
236
+
237
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
238
+ an owned object of type `T` with `std::forward<U>(u)`, using the
239
+ allocator *alloc*.
240
+
241
+ ``` cpp
242
+ template<class... Us>
243
+ constexpr explicit indirect(in_place_t, Us&&... us);
244
+ ```
245
+
246
+ *Constraints:*
247
+
248
+ - `is_constructible_v<T, Us...>` is `true`, and
249
+ - `is_default_constructible_v<Allocator>` is `true`.
250
+
251
+ *Effects:* Constructs an owned object of type `T` with
252
+ `std::forward<Us>(us)...`, using the allocator *alloc*.
253
+
254
+ ``` cpp
255
+ template<class... Us>
256
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a,
257
+ in_place_t, Us&& ...us);
258
+ ```
259
+
260
+ *Constraints:* `is_constructible_v<T, Us...>` is `true`.
261
+
262
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
263
+ an owned object of type `T` with `std::forward<Us>(us)...`, using the
264
+ allocator *alloc*.
265
+
266
+ ``` cpp
267
+ template<class I, class... Us>
268
+ constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us);
269
+ ```
270
+
271
+ *Constraints:*
272
+
273
+ - `is_constructible_v<T, initializer_list<I>&, Us...>` is `true`, and
274
+ - `is_default_constructible_v<Allocator>` is `true`.
275
+
276
+ *Effects:* Constructs an owned object of type `T` with the arguments
277
+ `ilist, std::forward<Us>(us)...`, using the allocator *alloc*.
278
+
279
+ ``` cpp
280
+ template<class I, class... Us>
281
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a,
282
+ in_place_t, initializer_list<I> ilist, Us&&... us);
283
+ ```
284
+
285
+ *Constraints:* `is_constructible_v<T, initializer_list<I>&, Us...>` is
286
+ `true`.
287
+
288
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
289
+ an owned object of type `T` with the arguments
290
+ `ilist, std::forward<Us>(us)...`, using the allocator *alloc*.
291
+
292
+ #### Destructor <a id="indirect.dtor">[[indirect.dtor]]</a>
293
+
294
+ ``` cpp
295
+ constexpr ~indirect();
296
+ ```
297
+
298
+ *Mandates:* `T` is a complete type.
299
+
300
+ *Effects:* If `*this` is not valueless, destroys the owned object using
301
+ `allocator_traits<Allocator>::destroy` and then the storage is
302
+ deallocated.
303
+
304
+ #### Assignment <a id="indirect.assign">[[indirect.assign]]</a>
305
+
306
+ ``` cpp
307
+ constexpr indirect& operator=(const indirect& other);
308
+ ```
309
+
310
+ *Mandates:*
311
+
312
+ - `is_copy_assignable_v<T>` is `true`, and
313
+ - `is_copy_constructible_v<T>` is `true`.
314
+
315
+ *Effects:* If `addressof(other) == this` is `true`, there are no
316
+ effects. Otherwise:
317
+
318
+ - The allocator needs updating if
319
+ `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value`
320
+ is `true`.
321
+ - If `other` is valueless, `*this` becomes valueless and the owned
322
+ object in `*this`, if any, is destroyed using
323
+ `allocator_traits<Allocator>::destroy` and then the storage is
324
+ deallocated.
325
+ - Otherwise, if *`alloc`*` == other.`*`alloc`* is `true` and `*this` is
326
+ not valueless, equivalent to `**this = *other`.
327
+ - Otherwise a new owned object is constructed in `*this` using
328
+ `allocator_traits<Allocator>::construct` with the owned object from
329
+ `other` as the argument, using either the allocator in `*this` or the
330
+ allocator in `other` if the allocator needs updating.
331
+ - The previously owned object in `*this`, if any, is destroyed using
332
+ `allocator_traits<Allocator>::destroy` and then the storage is
333
+ deallocated.
334
+ - If the allocator needs updating, the allocator in `*this` is replaced
335
+ with a copy of the allocator in `other`.
336
+
337
+ *Returns:* A reference to `*this`.
338
+
339
+ *Remarks:* If any exception is thrown, the result of the expression
340
+ `this->valueless_after_move()` remains unchanged. If an exception is
341
+ thrown during the call to `T`’s selected copy constructor, no effect. If
342
+ an exception is thrown during the call to `T`’s copy assignment, the
343
+ state of its owned object is as defined by the exception safety
344
+ guarantee of `T`’s copy assignment.
345
+
346
+ ``` cpp
347
+ constexpr indirect& operator=(indirect&& other)
348
+ noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
349
+ allocator_traits<Allocator>::is_always_equal::value);
350
+ ```
351
+
352
+ *Mandates:* `is_copy_constructible_v<T>` is `true`.
353
+
354
+ *Effects:* If `addressof(other) == this` is `true`, there are no
355
+ effects. Otherwise:
356
+
357
+ - The allocator needs updating if
358
+ `allocator_traits<Allocator>::propagate_on_container_move_assignment::value`
359
+ is `true`.
360
+ - If `other` is valueless, `*this` becomes valueless and the owned
361
+ object in `*this`, if any, is destroyed using
362
+ `allocator_traits<Allocator>::destroy` and then the storage is
363
+ deallocated.
364
+ - Otherwise, if *`alloc`*` == other.`*`alloc`* is `true`, swaps the
365
+ owned objects in `*this` and `other`; the owned object in `other`, if
366
+ any, is then destroyed using `allocator_traits<Allocator>::destroy`
367
+ and then the storage is deallocated.
368
+ - Otherwise, constructs a new owned object with the owned object of
369
+ `other` as the argument as an rvalue, using either the allocator in
370
+ `*this` or the allocator in `other` if the allocator needs updating.
371
+ - The previously owned object in `*this`, if any, is destroyed using
372
+ `allocator_traits<Allocator>::destroy` and then the storage is
373
+ deallocated.
374
+ - If the allocator needs updating, the allocator in `*this` is replaced
375
+ with a copy of the allocator in `other`.
376
+
377
+ *Ensures:* `other` is valueless.
378
+
379
+ *Returns:* A reference to `*this`.
380
+
381
+ *Remarks:* If any exception is thrown, there are no effects on `*this`
382
+ or `other`.
383
+
384
+ ``` cpp
385
+ template<class U = T>
386
+ constexpr indirect& operator=(U&& u);
387
+ ```
388
+
389
+ *Constraints:*
390
+
391
+ - `is_same_v<remove_cvref_t<U>, indirect>` is `false`,
392
+ - `is_constructible_v<T, U>` is `true`, and
393
+ - `is_assignable_v<T&, U>` is `true`.
394
+
395
+ *Effects:* If `*this` is valueless then constructs an owned object of
396
+ type `T` with `std::forward<U>(u)` using the allocator *alloc*.
397
+ Otherwise, equivalent to `**this = std::forward<U>(u)`.
398
+
399
+ *Returns:* A reference to `*this`.
400
+
401
+ #### Observers <a id="indirect.obs">[[indirect.obs]]</a>
402
+
403
+ ``` cpp
404
+ constexpr const T& operator*() const & noexcept;
405
+ constexpr T& operator*() & noexcept;
406
+ ```
407
+
408
+ *Preconditions:* `*this` is not valueless.
409
+
410
+ *Returns:* `*`*`p`*.
411
+
412
+ ``` cpp
413
+ constexpr const T&& operator*() const && noexcept;
414
+ constexpr T&& operator*() && noexcept;
415
+ ```
416
+
417
+ *Preconditions:* `*this` is not valueless.
418
+
419
+ *Returns:* `std::move(*`*`p`*`)`.
420
+
421
+ ``` cpp
422
+ constexpr const_pointer operator->() const noexcept;
423
+ constexpr pointer operator->() noexcept;
424
+ ```
425
+
426
+ *Preconditions:* `*this` is not valueless.
427
+
428
+ *Returns:* *p*.
429
+
430
+ ``` cpp
431
+ constexpr bool valueless_after_move() const noexcept;
432
+ ```
433
+
434
+ *Returns:* `true` if `*this` is valueless, otherwise `false`.
435
+
436
+ ``` cpp
437
+ constexpr allocator_type get_allocator() const noexcept;
438
+ ```
439
+
440
+ *Returns:* *alloc*.
441
+
442
+ #### Swap <a id="indirect.swap">[[indirect.swap]]</a>
443
+
444
+ ``` cpp
445
+ constexpr void swap(indirect& other)
446
+ noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
447
+ allocator_traits<Allocator>::is_always_equal::value);
448
+ ```
449
+
450
+ *Preconditions:* If
451
+ `allocator_traits<Allocator>::propagate_on_container_swap::value` is
452
+ `true`, then `Allocator` meets the *Cpp17Swappable* requirements.
453
+ Otherwise `get_allocator() == other.get_allocator()` is `true`.
454
+
455
+ *Effects:* Swaps the states of `*this` and `other`, exchanging owned
456
+ objects or valueless states. If
457
+ `allocator_traits<Allocator>::propagate_on_container_swap::value` is
458
+ `true`, then the allocators of `*this` and `other` are exchanged by
459
+ calling `swap` as described in  [[swappable.requirements]]. Otherwise,
460
+ the allocators are not swapped.
461
+
462
+ [*Note 1*: Does not call `swap` on the owned objects
463
+ directly. — *end note*]
464
+
465
+ ``` cpp
466
+ constexpr void swap(indirect& lhs, indirect& rhs) noexcept(noexcept(lhs.swap(rhs)));
467
+ ```
468
+
469
+ *Effects:* Equivalent to `lhs.swap(rhs)`.
470
+
471
+ #### Relational operators <a id="indirect.relops">[[indirect.relops]]</a>
472
+
473
+ ``` cpp
474
+ template<class U, class AA>
475
+ constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs)
476
+ noexcept(noexcept(*lhs == *rhs));
477
+ ```
478
+
479
+ *Mandates:* The expression `*lhs == *rhs` is well-formed and its result
480
+ is convertible to `bool`.
481
+
482
+ *Returns:* If `lhs` is valueless or `rhs` is valueless,
483
+ `lhs.valueless_after_move() == rhs.valueless_after_move()`; otherwise
484
+ `*lhs == *rhs`.
485
+
486
+ ``` cpp
487
+ template<class U, class AA>
488
+ constexpr synth-three-way-result<T, U>
489
+ operator<=>(const indirect& lhs, const indirect<U, AA>& rhs);
490
+ ```
491
+
492
+ *Returns:* If `lhs` is valueless or `rhs` is valueless,
493
+ `!lhs.valueless_after_move() <=> !rhs.valueless_after_move()`; otherwise
494
+ *`synth-three-way`*`(*lhs, *rhs)`.
495
+
496
+ #### Comparison with `T` <a id="indirect.comp.with.t">[[indirect.comp.with.t]]</a>
497
+
498
+ ``` cpp
499
+ template<class U>
500
+ constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(noexcept(*lhs == rhs));
501
+ ```
502
+
503
+ *Mandates:* The expression `*lhs == rhs` is well-formed and its result
504
+ is convertible to `bool`.
505
+
506
+ *Returns:* If `lhs` is valueless, `false`; otherwise `*lhs == rhs`.
507
+
508
+ ``` cpp
509
+ template<class U>
510
+ constexpr synth-three-way-result<T, U>
511
+ operator<=>(const indirect& lhs, const U& rhs);
512
+ ```
513
+
514
+ *Returns:* If `lhs` is valueless, `strong_ordering::less`; otherwise
515
+ *`synth-three-way`*`(*lhs, rhs)`.
516
+
517
+ #### Hash support <a id="indirect.hash">[[indirect.hash]]</a>
518
+
519
+ ``` cpp
520
+ template<class T, class Allocator>
521
+ struct hash<indirect<T, Allocator>>;
522
+ ```
523
+
524
+ The specialization `hash<indirect<T, Allocator>>` is
525
+ enabled [[unord.hash]] if and only if `hash<T>` is enabled. When enabled
526
+ for an object `i` of type `indirect<T, Allocator>`,
527
+ `hash<indirect<T, Allocator>>()(i)` evaluates to either the same value
528
+ as `hash<T>()(*i)`, if `i` is not valueless; otherwise to an
529
+ *implementation-defined* value. The member functions are not guaranteed
530
+ to be `noexcept`.
531
+