From Jason Turner

[mem.composite.types]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp9beqs3sz/{from.md → to.md} +958 -0
tmp/tmp9beqs3sz/{from.md → to.md} RENAMED
@@ -0,0 +1,958 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Types for composite class design <a id="mem.composite.types">[[mem.composite.types]]</a>
2
+
3
+ ### Class template `indirect` <a id="indirect">[[indirect]]</a>
4
+
5
+ #### General <a id="indirect.general">[[indirect.general]]</a>
6
+
7
+ An indirect object manages the lifetime of an owned object. An indirect
8
+ object is *valueless* if it has no owned object. An indirect object may
9
+ become valueless only after it has been moved from.
10
+
11
+ In every specialization `indirect<T, Allocator>`, if the type
12
+ `allocator_traits<Allocator>::value_type` is not the same type as `T`,
13
+ the program is ill-formed. Every object of type `indirect<T, Allocator>`
14
+ uses an object of type `Allocator` to allocate and free storage for the
15
+ owned object as needed.
16
+
17
+ Constructing an owned object with `args...` using the allocator `a`
18
+ means calling `allocator_traits<Allocator>::construct(a, p, args...)`
19
+ where `args` is an expression pack, `a` is an allocator, and *`p`* is a
20
+ pointer obtained by calling `allocator_traits<Allocator>::allocate`.
21
+
22
+ The member *`alloc`* is used for any memory allocation and element
23
+ construction performed by member functions during the lifetime of each
24
+ indirect object. The allocator *`alloc`* may be replaced only via
25
+ assignment or `swap()`. `Allocator` replacement is performed by copy
26
+ assignment, move assignment, or swapping of the allocator only if
27
+ [[container.reqmts]]:
28
+
29
+ - `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value`,
30
+ or
31
+ - `allocator_traits<Allocator>::propagate_on_container_move_assignment::value`,
32
+ or
33
+ - `allocator_traits<Allocator>::propagate_on_container_swap::value`
34
+
35
+ is `true` within the implementation of the corresponding `indirect`
36
+ operation.
37
+
38
+ A program that instantiates the definition of the template
39
+ `indirect<T, Allocator>` with a type for the `T` parameter that is a
40
+ non-object type, an array type, `in_place_t`, a specialization of
41
+ `in_place_type_t`, or a cv-qualified type is ill-formed.
42
+
43
+ The template parameter `T` of `indirect` may be an incomplete type.
44
+
45
+ The template parameter `Allocator` of `indirect` shall meet the
46
+ *Cpp17Allocator* requirements.
47
+
48
+ If a program declares an explicit or partial specialization of
49
+ `indirect`, the behavior is undefined.
50
+
51
+ #### Synopsis <a id="indirect.syn">[[indirect.syn]]</a>
52
+
53
+ ``` cpp
54
+ namespace std {
55
+ template<class T, class Allocator = allocator<T>>
56
+ class indirect {
57
+ public:
58
+ using value_type = T;
59
+ using allocator_type = Allocator;
60
+ using pointer = allocator_traits<Allocator>::pointer;
61
+ using const_pointer = allocator_traits<Allocator>::const_pointer;
62
+
63
+ // [indirect.ctor], constructors
64
+ constexpr explicit indirect();
65
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a);
66
+ constexpr indirect(const indirect& other);
67
+ constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other);
68
+ constexpr indirect(indirect&& other) noexcept;
69
+ constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other)
70
+ noexcept(see below);
71
+ template<class U = T>
72
+ constexpr explicit indirect(U&& u);
73
+ template<class U = T>
74
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u);
75
+ template<class... Us>
76
+ constexpr explicit indirect(in_place_t, Us&&... us);
77
+ template<class... Us>
78
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a,
79
+ in_place_t, Us&&... us);
80
+ template<class I, class... Us>
81
+ constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us);
82
+ template<class I, class... Us>
83
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a,
84
+ in_place_t, initializer_list<I> ilist, Us&&... us);
85
+
86
+ // [indirect.dtor], destructor
87
+ constexpr ~indirect();
88
+
89
+ // [indirect.assign], assignment
90
+ constexpr indirect& operator=(const indirect& other);
91
+ constexpr indirect& operator=(indirect&& other) noexcept(see below);
92
+ template<class U = T>
93
+ constexpr indirect& operator=(U&& u);
94
+
95
+ // [indirect.obs], observers
96
+ constexpr const T& operator*() const & noexcept;
97
+ constexpr T& operator*() & noexcept;
98
+ constexpr const T&& operator*() const && noexcept;
99
+ constexpr T&& operator*() && noexcept;
100
+ constexpr const_pointer operator->() const noexcept;
101
+ constexpr pointer operator->() noexcept;
102
+ constexpr bool valueless_after_move() const noexcept;
103
+ constexpr allocator_type get_allocator() const noexcept;
104
+
105
+ // [indirect.swap], swap
106
+ constexpr void swap(indirect& other) noexcept(see below);
107
+ friend constexpr void swap(indirect& lhs, indirect& rhs) noexcept(see below);
108
+
109
+ // [indirect.relops], relational operators
110
+ template<class U, class AA>
111
+ friend constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs)
112
+ noexcept(see below);
113
+ template<class U, class AA>
114
+ friend constexpr auto operator<=>(const indirect& lhs, const indirect<U, AA>& rhs)
115
+ -> synth-three-way-result<T, U>;
116
+
117
+ // [indirect.comp.with.t], comparison with T
118
+ template<class U>
119
+ friend constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(see below);
120
+ template<class U>
121
+ friend constexpr auto operator<=>(const indirect& lhs, const U& rhs)
122
+ -> synth-three-way-result<T, U>;
123
+
124
+ private:
125
+ pointer p; // exposition only
126
+ Allocator alloc = Allocator(); // exposition only
127
+ };
128
+ template<class Value>
129
+ indirect(Value) -> indirect<Value>;
130
+ template<class Allocator, class Value>
131
+ indirect(allocator_arg_t, Allocator, Value)
132
+ -> indirect<Value, typename allocator_traits<Allocator>::template rebind_alloc<Value>>;
133
+ }
134
+ ```
135
+
136
+ #### Constructors <a id="indirect.ctor">[[indirect.ctor]]</a>
137
+
138
+ The following element applies to all functions in  [[indirect.ctor]]:
139
+
140
+ *Throws:* Nothing unless `allocator_traits<Allocator>::allocate` or
141
+ `allocator_traits<Allocator>::construct` throws.
142
+
143
+ ``` cpp
144
+ constexpr explicit indirect();
145
+ ```
146
+
147
+ *Constraints:* `is_default_constructible_v<Allocator>` is `true`.
148
+
149
+ *Mandates:* `is_default_constructible_v<T>` is `true`.
150
+
151
+ *Effects:* Constructs an owned object of type `T` with an empty argument
152
+ list, using the allocator *alloc*.
153
+
154
+ ``` cpp
155
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a);
156
+ ```
157
+
158
+ *Mandates:* `is_default_constructible_v<T>` is `true`.
159
+
160
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
161
+ an owned object of type `T` with an empty argument list, using the
162
+ allocator *alloc*.
163
+
164
+ ``` cpp
165
+ constexpr indirect(const indirect& other);
166
+ ```
167
+
168
+ *Mandates:* `is_copy_constructible_v<T>` is `true`.
169
+
170
+ *Effects:* *alloc* is direct-non-list-initialized with
171
+ `allocator_traits<Allocator>::select_on_container_copy_construction(other.`*`alloc`*`)`.
172
+ If `other` is valueless, `*this` is valueless. Otherwise, constructs an
173
+ owned object of type `T` with `*other`, using the allocator *alloc*.
174
+
175
+ ``` cpp
176
+ constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other);
177
+ ```
178
+
179
+ *Mandates:* `is_copy_constructible_v<T>` is `true`.
180
+
181
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. If `other`
182
+ is valueless, `*this` is valueless. Otherwise, constructs an owned
183
+ object of type `T` with `*other`, using the allocator *alloc*.
184
+
185
+ ``` cpp
186
+ constexpr indirect(indirect&& other) noexcept;
187
+ ```
188
+
189
+ *Effects:* *alloc* is direct-non-list-initialized from
190
+ `std::move(other.`*`alloc`*`)`. If `other` is valueless, `*this` is
191
+ valueless. Otherwise `*this` takes ownership of the owned object of
192
+ `other`.
193
+
194
+ *Ensures:* `other` is valueless.
195
+
196
+ ``` cpp
197
+ constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other)
198
+ noexcept(allocator_traits<Allocator>::is_always_equal::value);
199
+ ```
200
+
201
+ *Mandates:* If `allocator_traits<Allocator>::is_always_equal::value` is
202
+ `false` then `T` is a complete type.
203
+
204
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. If `other`
205
+ is valueless, `*this` is valueless. Otherwise, if
206
+ *`alloc`*` == other.`*`alloc`* is `true`, constructs an object of type
207
+ `indirect` that takes ownership of the owned object of `other`.
208
+ Otherwise, constructs an owned object of type `T` with
209
+ `*std::move(other)`, using the allocator *alloc*.
210
+
211
+ *Ensures:* `other` is valueless.
212
+
213
+ ``` cpp
214
+ template<class U = T>
215
+ constexpr explicit indirect(U&& u);
216
+ ```
217
+
218
+ *Constraints:*
219
+
220
+ - `is_same_v<remove_cvref_t<U>, indirect>` is `false`,
221
+ - `is_same_v<remove_cvref_t<U>, in_place_t>` is `false`,
222
+ - `is_constructible_v<T, U>` is `true`, and
223
+ - `is_default_constructible_v<Allocator>` is `true`.
224
+
225
+ *Effects:* Constructs an owned object of type `T` with
226
+ `std::forward<U>(u)`, using the allocator *alloc*.
227
+
228
+ ``` cpp
229
+ template<class U = T>
230
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u);
231
+ ```
232
+
233
+ *Constraints:*
234
+
235
+ - `is_same_v<remove_cvref_t<U>, indirect>` is `false`,
236
+ - `is_same_v<remove_cvref_t<U>, in_place_t>` is `false`, and
237
+ - `is_constructible_v<T, U>` is `true`.
238
+
239
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
240
+ an owned object of type `T` with `std::forward<U>(u)`, using the
241
+ allocator *alloc*.
242
+
243
+ ``` cpp
244
+ template<class... Us>
245
+ constexpr explicit indirect(in_place_t, Us&&... us);
246
+ ```
247
+
248
+ *Constraints:*
249
+
250
+ - `is_constructible_v<T, Us...>` is `true`, and
251
+ - `is_default_constructible_v<Allocator>` is `true`.
252
+
253
+ *Effects:* Constructs an owned object of type `T` with
254
+ `std::forward<Us>(us)...`, using the allocator *alloc*.
255
+
256
+ ``` cpp
257
+ template<class... Us>
258
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a,
259
+ in_place_t, Us&& ...us);
260
+ ```
261
+
262
+ *Constraints:* `is_constructible_v<T, Us...>` is `true`.
263
+
264
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
265
+ an owned object of type `T` with `std::forward<Us>(us)...`, using the
266
+ allocator *alloc*.
267
+
268
+ ``` cpp
269
+ template<class I, class... Us>
270
+ constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us);
271
+ ```
272
+
273
+ *Constraints:*
274
+
275
+ - `is_constructible_v<T, initializer_list<I>&, Us...>` is `true`, and
276
+ - `is_default_constructible_v<Allocator>` is `true`.
277
+
278
+ *Effects:* Constructs an owned object of type `T` with the arguments
279
+ `ilist, std::forward<Us>(us)...`, using the allocator *alloc*.
280
+
281
+ ``` cpp
282
+ template<class I, class... Us>
283
+ constexpr explicit indirect(allocator_arg_t, const Allocator& a,
284
+ in_place_t, initializer_list<I> ilist, Us&&... us);
285
+ ```
286
+
287
+ *Constraints:* `is_constructible_v<T, initializer_list<I>&, Us...>` is
288
+ `true`.
289
+
290
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
291
+ an owned object of type `T` with the arguments
292
+ `ilist, std::forward<Us>(us)...`, using the allocator *alloc*.
293
+
294
+ #### Destructor <a id="indirect.dtor">[[indirect.dtor]]</a>
295
+
296
+ ``` cpp
297
+ constexpr ~indirect();
298
+ ```
299
+
300
+ *Mandates:* `T` is a complete type.
301
+
302
+ *Effects:* If `*this` is not valueless, destroys the owned object using
303
+ `allocator_traits<Allocator>::destroy` and then the storage is
304
+ deallocated.
305
+
306
+ #### Assignment <a id="indirect.assign">[[indirect.assign]]</a>
307
+
308
+ ``` cpp
309
+ constexpr indirect& operator=(const indirect& other);
310
+ ```
311
+
312
+ *Mandates:*
313
+
314
+ - `is_copy_assignable_v<T>` is `true`, and
315
+ - `is_copy_constructible_v<T>` is `true`.
316
+
317
+ *Effects:* If `addressof(other) == this` is `true`, there are no
318
+ effects. Otherwise:
319
+
320
+ - The allocator needs updating if
321
+ `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value`
322
+ is `true`.
323
+ - If `other` is valueless, `*this` becomes valueless and the owned
324
+ object in `*this`, if any, is destroyed using
325
+ `allocator_traits<Allocator>::destroy` and then the storage is
326
+ deallocated.
327
+ - Otherwise, if *`alloc`*` == other.`*`alloc`* is `true` and `*this` is
328
+ not valueless, equivalent to `**this = *other`.
329
+ - Otherwise a new owned object is constructed in `*this` using
330
+ `allocator_traits<Allocator>::construct` with the owned object from
331
+ `other` as the argument, using either the allocator in `*this` or the
332
+ allocator in `other` if the allocator needs updating.
333
+ - The previously owned object in `*this`, if any, is destroyed using
334
+ `allocator_traits<Allocator>::destroy` and then the storage is
335
+ deallocated.
336
+ - If the allocator needs updating, the allocator in `*this` is replaced
337
+ with a copy of the allocator in `other`.
338
+
339
+ *Returns:* A reference to `*this`.
340
+
341
+ *Remarks:* If any exception is thrown, the result of the expression
342
+ `this->valueless_after_move()` remains unchanged. If an exception is
343
+ thrown during the call to `T`’s selected copy constructor, no effect. If
344
+ an exception is thrown during the call to `T`’s copy assignment, the
345
+ state of its owned object is as defined by the exception safety
346
+ guarantee of `T`’s copy assignment.
347
+
348
+ ``` cpp
349
+ constexpr indirect& operator=(indirect&& other)
350
+ noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
351
+ allocator_traits<Allocator>::is_always_equal::value);
352
+ ```
353
+
354
+ *Mandates:* `is_copy_constructible_v<T>` is `true`.
355
+
356
+ *Effects:* If `addressof(other) == this` is `true`, there are no
357
+ effects. Otherwise:
358
+
359
+ - The allocator needs updating if
360
+ `allocator_traits<Allocator>::propagate_on_container_move_assignment::value`
361
+ is `true`.
362
+ - If `other` is valueless, `*this` becomes valueless and the owned
363
+ object in `*this`, if any, is destroyed using
364
+ `allocator_traits<Allocator>::destroy` and then the storage is
365
+ deallocated.
366
+ - Otherwise, if *`alloc`*` == other.`*`alloc`* is `true`, swaps the
367
+ owned objects in `*this` and `other`; the owned object in `other`, if
368
+ any, is then destroyed using `allocator_traits<Allocator>::destroy`
369
+ and then the storage is deallocated.
370
+ - Otherwise, constructs a new owned object with the owned object of
371
+ `other` as the argument as an rvalue, using either the allocator in
372
+ `*this` or the allocator in `other` if the allocator needs updating.
373
+ - The previously owned object in `*this`, if any, is destroyed using
374
+ `allocator_traits<Allocator>::destroy` and then the storage is
375
+ deallocated.
376
+ - If the allocator needs updating, the allocator in `*this` is replaced
377
+ with a copy of the allocator in `other`.
378
+
379
+ *Ensures:* `other` is valueless.
380
+
381
+ *Returns:* A reference to `*this`.
382
+
383
+ *Remarks:* If any exception is thrown, there are no effects on `*this`
384
+ or `other`.
385
+
386
+ ``` cpp
387
+ template<class U = T>
388
+ constexpr indirect& operator=(U&& u);
389
+ ```
390
+
391
+ *Constraints:*
392
+
393
+ - `is_same_v<remove_cvref_t<U>, indirect>` is `false`,
394
+ - `is_constructible_v<T, U>` is `true`, and
395
+ - `is_assignable_v<T&, U>` is `true`.
396
+
397
+ *Effects:* If `*this` is valueless then constructs an owned object of
398
+ type `T` with `std::forward<U>(u)` using the allocator *alloc*.
399
+ Otherwise, equivalent to `**this = std::forward<U>(u)`.
400
+
401
+ *Returns:* A reference to `*this`.
402
+
403
+ #### Observers <a id="indirect.obs">[[indirect.obs]]</a>
404
+
405
+ ``` cpp
406
+ constexpr const T& operator*() const & noexcept;
407
+ constexpr T& operator*() & noexcept;
408
+ ```
409
+
410
+ *Preconditions:* `*this` is not valueless.
411
+
412
+ *Returns:* `*`*`p`*.
413
+
414
+ ``` cpp
415
+ constexpr const T&& operator*() const && noexcept;
416
+ constexpr T&& operator*() && noexcept;
417
+ ```
418
+
419
+ *Preconditions:* `*this` is not valueless.
420
+
421
+ *Returns:* `std::move(*`*`p`*`)`.
422
+
423
+ ``` cpp
424
+ constexpr const_pointer operator->() const noexcept;
425
+ constexpr pointer operator->() noexcept;
426
+ ```
427
+
428
+ *Preconditions:* `*this` is not valueless.
429
+
430
+ *Returns:* *p*.
431
+
432
+ ``` cpp
433
+ constexpr bool valueless_after_move() const noexcept;
434
+ ```
435
+
436
+ *Returns:* `true` if `*this` is valueless, otherwise `false`.
437
+
438
+ ``` cpp
439
+ constexpr allocator_type get_allocator() const noexcept;
440
+ ```
441
+
442
+ *Returns:* *alloc*.
443
+
444
+ #### Swap <a id="indirect.swap">[[indirect.swap]]</a>
445
+
446
+ ``` cpp
447
+ constexpr void swap(indirect& other)
448
+ noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
449
+ allocator_traits<Allocator>::is_always_equal::value);
450
+ ```
451
+
452
+ *Preconditions:* If
453
+ `allocator_traits<Allocator>::propagate_on_container_swap::value` is
454
+ `true`, then `Allocator` meets the *Cpp17Swappable* requirements.
455
+ Otherwise `get_allocator() == other.get_allocator()` is `true`.
456
+
457
+ *Effects:* Swaps the states of `*this` and `other`, exchanging owned
458
+ objects or valueless states. If
459
+ `allocator_traits<Allocator>::propagate_on_container_swap::value` is
460
+ `true`, then the allocators of `*this` and `other` are exchanged by
461
+ calling `swap` as described in  [[swappable.requirements]]. Otherwise,
462
+ the allocators are not swapped.
463
+
464
+ [*Note 1*: Does not call `swap` on the owned objects
465
+ directly. — *end note*]
466
+
467
+ ``` cpp
468
+ constexpr void swap(indirect& lhs, indirect& rhs) noexcept(noexcept(lhs.swap(rhs)));
469
+ ```
470
+
471
+ *Effects:* Equivalent to `lhs.swap(rhs)`.
472
+
473
+ #### Relational operators <a id="indirect.relops">[[indirect.relops]]</a>
474
+
475
+ ``` cpp
476
+ template<class U, class AA>
477
+ constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs)
478
+ noexcept(noexcept(*lhs == *rhs));
479
+ ```
480
+
481
+ *Mandates:* The expression `*lhs == *rhs` is well-formed and its result
482
+ is convertible to `bool`.
483
+
484
+ *Returns:* If `lhs` is valueless or `rhs` is valueless,
485
+ `lhs.valueless_after_move() == rhs.valueless_after_move()`; otherwise
486
+ `*lhs == *rhs`.
487
+
488
+ ``` cpp
489
+ template<class U, class AA>
490
+ constexpr synth-three-way-result<T, U>
491
+ operator<=>(const indirect& lhs, const indirect<U, AA>& rhs);
492
+ ```
493
+
494
+ *Returns:* If `lhs` is valueless or `rhs` is valueless,
495
+ `!lhs.valueless_after_move() <=> !rhs.valueless_after_move()`; otherwise
496
+ *`synth-three-way`*`(*lhs, *rhs)`.
497
+
498
+ #### Comparison with `T` <a id="indirect.comp.with.t">[[indirect.comp.with.t]]</a>
499
+
500
+ ``` cpp
501
+ template<class U>
502
+ constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(noexcept(*lhs == rhs));
503
+ ```
504
+
505
+ *Mandates:* The expression `*lhs == rhs` is well-formed and its result
506
+ is convertible to `bool`.
507
+
508
+ *Returns:* If `lhs` is valueless, `false`; otherwise `*lhs == rhs`.
509
+
510
+ ``` cpp
511
+ template<class U>
512
+ constexpr synth-three-way-result<T, U>
513
+ operator<=>(const indirect& lhs, const U& rhs);
514
+ ```
515
+
516
+ *Returns:* If `lhs` is valueless, `strong_ordering::less`; otherwise
517
+ *`synth-three-way`*`(*lhs, rhs)`.
518
+
519
+ #### Hash support <a id="indirect.hash">[[indirect.hash]]</a>
520
+
521
+ ``` cpp
522
+ template<class T, class Allocator>
523
+ struct hash<indirect<T, Allocator>>;
524
+ ```
525
+
526
+ The specialization `hash<indirect<T, Allocator>>` is
527
+ enabled [[unord.hash]] if and only if `hash<T>` is enabled. When enabled
528
+ for an object `i` of type `indirect<T, Allocator>`,
529
+ `hash<indirect<T, Allocator>>()(i)` evaluates to either the same value
530
+ as `hash<T>()(*i)`, if `i` is not valueless; otherwise to an
531
+ *implementation-defined* value. The member functions are not guaranteed
532
+ to be `noexcept`.
533
+
534
+ ### Class template `polymorphic` <a id="polymorphic">[[polymorphic]]</a>
535
+
536
+ #### General <a id="polymorphic.general">[[polymorphic.general]]</a>
537
+
538
+ A polymorphic object manages the lifetime of an owned object. A
539
+ polymorphic object may own objects of different types at different
540
+ points in its lifetime. A polymorphic object is *valueless* if it has no
541
+ owned object. A polymorphic object may become valueless only after it
542
+ has been moved from.
543
+
544
+ In every specialization `polymorphic<T, Allocator>`, if the type
545
+ `allocator_traits<Allocator>::value_type` is not the same type as `T`,
546
+ the program is ill-formed. Every object of type
547
+ `polymorphic<T, Allocator>` uses an object of type `Allocator` to
548
+ allocate and free storage for the owned object as needed.
549
+
550
+ Constructing an owned object of type `U` with `args...` using the
551
+ allocator `a` means calling
552
+ `allocator_traits<Allocator>::construct(a, p, args...)` where `args` is
553
+ an expression pack, `a` is an allocator, and *`p`* points to storage
554
+ suitable for an owned object of type `U`.
555
+
556
+ The member *`alloc`* is used for any memory allocation and element
557
+ construction performed by member functions during the lifetime of each
558
+ polymorphic value object, or until the allocator is replaced. The
559
+ allocator may be replaced only via assignment or `swap()`. `Allocator`
560
+ replacement is performed by copy assignment, move assignment, or
561
+ swapping of the allocator only if [[container.reqmts]]:
562
+
563
+ - `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value`,
564
+ or
565
+ - `allocator_traits<Allocator>::propagate_on_container_move_assignment::value`,
566
+ or
567
+ - `allocator_traits<Allocator>::propagate_on_container_swap::value`
568
+
569
+ is `true` within the implementation of the corresponding `polymorphic`
570
+ operation.
571
+
572
+ A program that instantiates the definition of `polymorphic` for a
573
+ non-object type, an array type, `in_place_t`, a specialization of
574
+ `in_place_type_t`, or a cv-qualified type is ill-formed.
575
+
576
+ The template parameter `T` of `polymorphic` may be an incomplete type.
577
+
578
+ The template parameter `Allocator` of `polymorphic` shall meet the
579
+ requirements of *Cpp17Allocator*.
580
+
581
+ If a program declares an explicit or partial specialization of
582
+ `polymorphic`, the behavior is undefined.
583
+
584
+ #### Synopsis <a id="polymorphic.syn">[[polymorphic.syn]]</a>
585
+
586
+ ``` cpp
587
+ namespace std {
588
+ template<class T, class Allocator = allocator<T>>
589
+ class polymorphic {
590
+ public:
591
+ using value_type = T;
592
+ using allocator_type = Allocator;
593
+ using pointer = allocator_traits<Allocator>::pointer;
594
+ using const_pointer = allocator_traits<Allocator>::const_pointer;
595
+
596
+ // [polymorphic.ctor], constructors
597
+ constexpr explicit polymorphic();
598
+ constexpr explicit polymorphic(allocator_arg_t, const Allocator& a);
599
+ constexpr polymorphic(const polymorphic& other);
600
+ constexpr polymorphic(allocator_arg_t, const Allocator& a, const polymorphic& other);
601
+ constexpr polymorphic(polymorphic&& other) noexcept;
602
+ constexpr polymorphic(allocator_arg_t, const Allocator& a, polymorphic&& other)
603
+ noexcept(see below);
604
+ template<class U = T>
605
+ constexpr explicit polymorphic(U&& u);
606
+ template<class U = T>
607
+ constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, U&& u);
608
+ template<class U, class... Ts>
609
+ constexpr explicit polymorphic(in_place_type_t<U>, Ts&&... ts);
610
+ template<class U, class... Ts>
611
+ constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
612
+ in_place_type_t<U>, Ts&&... ts);
613
+ template<class U, class I, class... Us>
614
+ constexpr explicit polymorphic(in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);
615
+ template<class U, class I, class... Us>
616
+ constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
617
+ in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);
618
+
619
+ // [polymorphic.dtor], destructor
620
+ constexpr ~polymorphic();
621
+
622
+ // [polymorphic.assign], assignment
623
+ constexpr polymorphic& operator=(const polymorphic& other);
624
+ constexpr polymorphic& operator=(polymorphic&& other) noexcept(see below);
625
+
626
+ // [polymorphic.obs], observers
627
+ constexpr const T& operator*() const noexcept;
628
+ constexpr T& operator*() noexcept;
629
+ constexpr const_pointer operator->() const noexcept;
630
+ constexpr pointer operator->() noexcept;
631
+ constexpr bool valueless_after_move() const noexcept;
632
+ constexpr allocator_type get_allocator() const noexcept;
633
+
634
+ // [polymorphic.swap], swap
635
+ constexpr void swap(polymorphic& other) noexcept(see below);
636
+ friend constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(see below);
637
+
638
+ private:
639
+ Allocator alloc = Allocator(); // exposition only
640
+ };
641
+ }
642
+ ```
643
+
644
+ #### Constructors <a id="polymorphic.ctor">[[polymorphic.ctor]]</a>
645
+
646
+ The following element applies to all functions in  [[polymorphic.ctor]]:
647
+
648
+ *Throws:* Nothing unless `allocator_traits<Allocator>::allocate` or
649
+ `allocator_traits<Allocator>::construct` throws.
650
+
651
+ ``` cpp
652
+ constexpr explicit polymorphic();
653
+ ```
654
+
655
+ *Constraints:* `is_default_constructible_v<Allocator>` is `true`.
656
+
657
+ *Mandates:*
658
+
659
+ - `is_default_constructible_v<T>` is `true`, and
660
+ - `is_copy_constructible_v<T>` is `true`.
661
+
662
+ *Effects:* Constructs an owned object of type `T` with an empty argument
663
+ list using the allocator *alloc*.
664
+
665
+ ``` cpp
666
+ constexpr explicit polymorphic(allocator_arg_t, const Allocator& a);
667
+ ```
668
+
669
+ *Mandates:*
670
+
671
+ - `is_default_constructible_v<T>` is `true`, and
672
+ - `is_copy_constructible_v<T>` is `true`.
673
+
674
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
675
+ an owned object of type `T` with an empty argument list using the
676
+ allocator *alloc*.
677
+
678
+ ``` cpp
679
+ constexpr polymorphic(const polymorphic& other);
680
+ ```
681
+
682
+ *Effects:* *alloc* is direct-non-list-initialized with
683
+ `allocator_traits<Allocator>::select_on_container_copy_construction(other.`*`alloc`*`)`.
684
+ If `other` is valueless, `*this` is valueless. Otherwise, constructs an
685
+ owned object of type `U`, where `U` is the type of the owned object in
686
+ `other`, with the owned object in `other` using the allocator *alloc*.
687
+
688
+ ``` cpp
689
+ constexpr polymorphic(allocator_arg_t, const Allocator& a, const polymorphic& other);
690
+ ```
691
+
692
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. If `other`
693
+ is valueless, `*this` is valueless. Otherwise, constructs an owned
694
+ object of type `U`, where `U` is the type of the owned object in
695
+ `other`, with the owned object in `other` using the allocator *alloc*.
696
+
697
+ ``` cpp
698
+ constexpr polymorphic(polymorphic&& other) noexcept;
699
+ ```
700
+
701
+ *Effects:* *alloc* is direct-non-list-initialized with
702
+ `std::move(other.`*`alloc`*`)`. If `other` is valueless, `*this` is
703
+ valueless. Otherwise, either `*this` takes ownership of the owned object
704
+ of `other` or, owns an object of the same type constructed from the
705
+ owned object of `other` considering that owned object as an rvalue,
706
+ using the allocator *alloc*.
707
+
708
+ ``` cpp
709
+ constexpr polymorphic(allocator_arg_t, const Allocator& a, polymorphic&& other)
710
+ noexcept(allocator_traits<Allocator>::is_always_equal::value);
711
+ ```
712
+
713
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. If `other`
714
+ is valueless, `*this` is valueless. Otherwise, if
715
+ *`alloc`*` == other.`*`alloc`* is `true`, either constructs an object of
716
+ type `polymorphic` that owns the owned object of `other`, making `other`
717
+ valueless; or, owns an object of the same type constructed from the
718
+ owned object of `other` considering that owned object as an rvalue.
719
+ Otherwise, if *`alloc`*` != other.`*`alloc`* is `true`, constructs an
720
+ object of type `polymorphic`, considering the owned object in `other` as
721
+ an rvalue, using the allocator *alloc*.
722
+
723
+ ``` cpp
724
+ template<class U = T>
725
+ constexpr explicit polymorphic(U&& u);
726
+ ```
727
+
728
+ *Constraints:* Where `UU` is `remove_cvref_t<U>`,
729
+
730
+ - `is_same_v<UU, polymorphic>` is `false`,
731
+ - `derived_from<UU, T>` is `true`,
732
+ - `is_constructible_v<UU, U>` is `true`,
733
+ - `is_copy_constructible_v<UU>` is `true`,
734
+ - `UU` is not a specialization of `in_place_type_t`, and
735
+ - `is_default_constructible_v<Allocator>` is `true`.
736
+
737
+ *Effects:* Constructs an owned object of type `UU` with
738
+ `std::forward<U>(u)` using the allocator *alloc*.
739
+
740
+ ``` cpp
741
+ template<class U = T>
742
+ constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, U&& u);
743
+ ```
744
+
745
+ *Constraints:* Where `UU` is `remove_cvref_t<U>`,
746
+
747
+ - `is_same_v<UU, polymorphic>` is `false`,
748
+ - `derived_from<UU, T>` is `true`,
749
+ - `is_constructible_v<UU, U>` is `true`,
750
+ - `is_copy_constructible_v<UU>` is `true`, and
751
+ - `UU` is not a specialization of `in_place_type_t`.
752
+
753
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
754
+ an owned object of type `UU` with `std::forward<U>(u)` using the
755
+ allocator *alloc*.
756
+
757
+ ``` cpp
758
+ template<class U, class... Ts>
759
+ constexpr explicit polymorphic(in_place_type_t<U>, Ts&&... ts);
760
+ ```
761
+
762
+ *Constraints:*
763
+
764
+ - `is_same_v<remove_cvref_t<U>, U>` is `true`,
765
+ - `derived_from<U, T>` is `true`,
766
+ - `is_constructible_v<U, Ts...>` is `true`,
767
+ - `is_copy_constructible_v<U>` is `true`, and
768
+ - `is_default_constructible_v<Allocator>` is `true`.
769
+
770
+ *Effects:* Constructs an owned object of type `U` with
771
+ `std::forward<Ts>(ts)...` using the allocator *alloc*.
772
+
773
+ ``` cpp
774
+ template<class U, class... Ts>
775
+ constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
776
+ in_place_type_t<U>, Ts&&... ts);
777
+ ```
778
+
779
+ *Constraints:*
780
+
781
+ - `is_same_v<remove_cvref_t<U>, U>` is `true`,
782
+ - `derived_from<U, T>` is `true`,
783
+ - `is_constructible_v<U, Ts...>` is `true`, and
784
+ - `is_copy_constructible_v<U>` is `true`.
785
+
786
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
787
+ an owned object of type `U` with `std::forward<Ts>(ts)...` using the
788
+ allocator *alloc*.
789
+
790
+ ``` cpp
791
+ template<class U, class I, class... Us>
792
+ constexpr explicit polymorphic(in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);
793
+ ```
794
+
795
+ *Constraints:*
796
+
797
+ - `is_same_v<remove_cvref_t<U>, U>` is `true`,
798
+ - `derived_from<U, T>` is `true`,
799
+ - `is_constructible_v<U, initializer_list<I>&, Us...>` is `true`,
800
+ - `is_copy_constructible_v<U>` is `true`, and
801
+ - `is_default_constructible_v<Allocator>` is `true`.
802
+
803
+ *Effects:* Constructs an owned object of type `U` with the arguments
804
+ `ilist, std::forward<Us>(us)...` using the allocator *alloc*.
805
+
806
+ ``` cpp
807
+ template<class U, class I, class... Us>
808
+ constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
809
+ in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);
810
+ ```
811
+
812
+ *Constraints:*
813
+
814
+ - `is_same_v<remove_cvref_t<U>, U>` is `true`,
815
+ - `derived_from<U, T>` is `true`,
816
+ - `is_constructible_v<U, initializer_list<I>&, Us...>` is `true`, and
817
+ - `is_copy_constructible_v<U>` is `true`.
818
+
819
+ *Effects:* *alloc* is direct-non-list-initialized with `a`. Constructs
820
+ an owned object of type `U` with the arguments
821
+ `ilist, std::forward<Us>(us)...` using the allocator *alloc*.
822
+
823
+ #### Destructor <a id="polymorphic.dtor">[[polymorphic.dtor]]</a>
824
+
825
+ ``` cpp
826
+ constexpr ~polymorphic();
827
+ ```
828
+
829
+ *Mandates:* `T` is a complete type.
830
+
831
+ *Effects:* If `*this` is not valueless, destroys the owned object using
832
+ `allocator_traits<Allocator>::destroy` and then the storage is
833
+ deallocated.
834
+
835
+ #### Assignment <a id="polymorphic.assign">[[polymorphic.assign]]</a>
836
+
837
+ ``` cpp
838
+ constexpr polymorphic& operator=(const polymorphic& other);
839
+ ```
840
+
841
+ *Mandates:* `T` is a complete type.
842
+
843
+ *Effects:* If `addressof(other) == this` is `true`, there are no
844
+ effects. Otherwise:
845
+
846
+ - The allocator needs updating if
847
+ `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value`
848
+ is `true`.
849
+ - If `other` is not valueless, a new owned object is constructed in
850
+ `*this` using `allocator_traits<Allocator>::construct` with the owned
851
+ object from `other` as the argument, using either the allocator in
852
+ `*this` or the allocator in `other` if the allocator needs updating.
853
+ - The previously owned object in `*this`, if any, is destroyed using
854
+ `allocator_traits<Allocator>::destroy` and then the storage is
855
+ deallocated.
856
+ - If the allocator needs updating, the allocator in `*this` is replaced
857
+ with a copy of the allocator in `other`.
858
+
859
+ *Returns:* A reference to `*this`.
860
+
861
+ *Remarks:* If any exception is thrown, there are no effects on `*this`.
862
+
863
+ ``` cpp
864
+ constexpr polymorphic& operator=(polymorphic&& other)
865
+ noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
866
+ allocator_traits<Allocator>::is_always_equal::value);
867
+ ```
868
+
869
+ *Mandates:* If `allocator_traits<Allocator>::is_always_equal::value` is
870
+ `false`, `T` is a complete type.
871
+
872
+ *Effects:* If `addressof(other) == this` is `true`, there are no
873
+ effects. Otherwise:
874
+
875
+ - The allocator needs updating if
876
+ `allocator_traits<Allocator>::propagate_on_container_move_assignment::value`
877
+ is `true`.
878
+ - If *`alloc`*` == other.`*`alloc`* is `true`, swaps the owned objects
879
+ in `*this` and `other`; the owned object in `other`, if any, is then
880
+ destroyed using `allocator_traits<Allocator>::destroy` and then the
881
+ storage is deallocated.
882
+ - Otherwise, if *`alloc`*` != other.`*`alloc`* is `true`; if `other` is
883
+ not valueless, a new owned object is constructed in `*this` using
884
+ `allocator_traits<Allocator>::construct` with the owned object from
885
+ `other` as the argument as an rvalue, using either the allocator in
886
+ `*this` or the allocator in `other` if the allocator needs updating.
887
+ - The previously owned object in `*this`, if any, is destroyed using
888
+ `allocator_traits<Allocator>::destroy` and then the storage is
889
+ deallocated.
890
+ - If the allocator needs updating, the allocator in `*this` is replaced
891
+ with a copy of the allocator in `other`.
892
+
893
+ *Returns:* A reference to `*this`.
894
+
895
+ *Remarks:* If any exception is thrown, there are no effects on `*this`
896
+ or `other`.
897
+
898
+ #### Observers <a id="polymorphic.obs">[[polymorphic.obs]]</a>
899
+
900
+ ``` cpp
901
+ constexpr const T& operator*() const noexcept;
902
+ constexpr T& operator*() noexcept;
903
+ ```
904
+
905
+ *Preconditions:* `*this` is not valueless.
906
+
907
+ *Returns:* A reference to the owned object.
908
+
909
+ ``` cpp
910
+ constexpr const_pointer operator->() const noexcept;
911
+ constexpr pointer operator->() noexcept;
912
+ ```
913
+
914
+ *Preconditions:* `*this` is not valueless.
915
+
916
+ *Returns:* A pointer to the owned object.
917
+
918
+ ``` cpp
919
+ constexpr bool valueless_after_move() const noexcept;
920
+ ```
921
+
922
+ *Returns:* `true` if `*this` is valueless, otherwise `false`.
923
+
924
+ ``` cpp
925
+ constexpr allocator_type get_allocator() const noexcept;
926
+ ```
927
+
928
+ *Returns:* *alloc*.
929
+
930
+ #### Swap <a id="polymorphic.swap">[[polymorphic.swap]]</a>
931
+
932
+ ``` cpp
933
+ constexpr void swap(polymorphic& other)
934
+ noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
935
+ allocator_traits<Allocator>::is_always_equal::value);
936
+ ```
937
+
938
+ *Preconditions:* If
939
+ `allocator_traits<Allocator>::propagate_on_container_swap::value` is
940
+ `true`, then `Allocator` meets the *Cpp17Swappable* requirements.
941
+ Otherwise `get_allocator() == other.get_allocator()` is `true`.
942
+
943
+ *Effects:* Swaps the states of `*this` and `other`, exchanging owned
944
+ objects or valueless states. If
945
+ `allocator_traits<Allocator>::propagate_on_container_swap::value` is
946
+ `true`, then the allocators of `*this` and `other` are exchanged by
947
+ calling `swap` as described in  [[swappable.requirements]]. Otherwise,
948
+ the allocators are not swapped.
949
+
950
+ [*Note 1*: Does not call `swap` on the owned objects
951
+ directly. — *end note*]
952
+
953
+ ``` cpp
954
+ constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(noexcept(lhs.swap(rhs)));
955
+ ```
956
+
957
+ *Effects:* Equivalent to `lhs.swap(rhs)`.
958
+