From Jason Turner

[allocator.adaptor]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpamcipx1x/{from.md → to.md} +173 -107
tmp/tmpamcipx1x/{from.md → to.md} RENAMED
@@ -29,41 +29,44 @@ allocator is the outer allocator for use by the container, the second
29
  allocator is passed to the constructors of the container’s elements,
30
  and, if the elements themselves are containers, the third allocator is
31
  passed to the elements’ elements, and so on. If containers are nested to
32
  a depth greater than the number of allocators, the last allocator is
33
  used repeatedly, as in the single-allocator case, for any remaining
34
- recursions. The `scoped_allocator_adaptor` is derived from the outer
 
 
35
  allocator type so it can be substituted for the outer allocator type in
36
- most expressions.
37
 
38
  ``` cpp
39
  namespace std {
40
  template <class OuterAlloc, class... InnerAllocs>
41
  class scoped_allocator_adaptor : public OuterAlloc {
42
  private:
43
- typedef allocator_traits<OuterAlloc> OuterTraits; // exposition only
44
  scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only
45
  public:
46
- typedef OuterAlloc outer_allocator_type;
47
- typedef see below inner_allocator_type;
48
 
49
- typedef typename OuterTraits::value_type value_type;
50
- typedef typename OuterTraits::size_type size_type;
51
- typedef typename OuterTraits::difference_type difference_type;
52
- typedef typename OuterTraits::pointer pointer;
53
- typedef typename OuterTraits::const_pointer const_pointer;
54
- typedef typename OuterTraits::void_pointer void_pointer;
55
- typedef typename OuterTraits::const_void_pointer const_void_pointer;
56
 
57
- typedef see below propagate_on_container_copy_assignment;
58
- typedef see below propagate_on_container_move_assignment;
59
- typedef see below propagate_on_container_swap;
 
60
 
61
  template <class Tp>
62
  struct rebind {
63
- typedef scoped_allocator_adaptor<
64
- OuterTraits::template rebind_alloc<Tp>, InnerAllocs...> other;
65
  };
66
 
67
  scoped_allocator_adaptor();
68
  template <class OuterA2>
69
  scoped_allocator_adaptor(OuterA2&& outerAlloc,
@@ -77,10 +80,13 @@ namespace std {
77
  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
78
  template <class OuterA2>
79
  scoped_allocator_adaptor(
80
  scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
81
 
 
 
 
82
  ~scoped_allocator_adaptor();
83
 
84
  inner_allocator_type& inner_allocator() noexcept;
85
  const inner_allocator_type& inner_allocator() const noexcept;
86
  outer_allocator_type& outer_allocator() noexcept;
@@ -109,10 +115,14 @@ namespace std {
109
  void destroy(T* p);
110
 
111
  scoped_allocator_adaptor select_on_container_copy_construction() const;
112
  };
113
 
 
 
 
 
114
  template <class OuterA1, class OuterA2, class... InnerAllocs>
115
  bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
116
  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
117
  template <class OuterA1, class OuterA2, class... InnerAllocs>
118
  bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
@@ -121,113 +131,124 @@ namespace std {
121
  ```
122
 
123
  ### Scoped allocator adaptor member types <a id="allocator.adaptor.types">[[allocator.adaptor.types]]</a>
124
 
125
  ``` cpp
126
- typedef see below inner_allocator_type;
127
  ```
128
 
129
  *Type:* `scoped_allocator_adaptor<OuterAlloc>` if
130
  `sizeof...(InnerAllocs)` is zero; otherwise,
131
  `scoped_allocator_adaptor<InnerAllocs...>`.
132
 
133
  ``` cpp
134
- typedef see below propagate_on_container_copy_assignment;
135
  ```
136
 
137
  *Type:* `true_type` if
138
  `allocator_traits<A>::propagate_on_container_copy_assignment::value` is
139
  `true` for any `A` in the set of `OuterAlloc` and `InnerAllocs...`;
140
  otherwise, `false_type`.
141
 
142
  ``` cpp
143
- typedef see below propagate_on_container_move_assignment;
144
  ```
145
 
146
  *Type:* `true_type` if
147
  `allocator_traits<A>::propagate_on_container_move_assignment::value` is
148
  `true` for any `A` in the set of `OuterAlloc` and `InnerAllocs...`;
149
  otherwise, `false_type`.
150
 
151
  ``` cpp
152
- typedef see below propagate_on_container_swap;
153
  ```
154
 
155
  *Type:* `true_type` if
156
  `allocator_traits<A>::propagate_on_container_swap::value` is `true` for
157
  any `A` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise,
158
  `false_type`.
159
 
 
 
 
 
 
 
 
 
160
  ### Scoped allocator adaptor constructors <a id="allocator.adaptor.cnstr">[[allocator.adaptor.cnstr]]</a>
161
 
162
  ``` cpp
163
  scoped_allocator_adaptor();
164
  ```
165
 
166
- *Effects:* value-initializes the `OuterAlloc` base class and the `inner`
167
  allocator object.
168
 
169
  ``` cpp
170
  template <class OuterA2>
171
  scoped_allocator_adaptor(OuterA2&& outerAlloc,
172
  const InnerAllocs&... innerAllocs) noexcept;
173
  ```
174
 
175
- *Requires:* `OuterAlloc` shall be constructible from `OuterA2`.
176
-
177
- *Effects:* initializes the `OuterAlloc` base class with
178
  `std::forward<OuterA2>(outerAlloc)` and `inner` with `innerAllocs...`
179
  (hence recursively initializing each allocator within the adaptor with
180
  the corresponding allocator from the argument list).
181
 
 
 
 
182
  ``` cpp
183
  scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
184
  ```
185
 
186
- *Effects:* initializes each allocator within the adaptor with the
187
  corresponding allocator from `other`.
188
 
189
  ``` cpp
190
  scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
191
  ```
192
 
193
- *Effects:* move constructs each allocator within the adaptor with the
194
  corresponding allocator from `other`.
195
 
196
  ``` cpp
197
  template <class OuterA2>
198
  scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2,
199
  InnerAllocs...>& other) noexcept;
200
  ```
201
 
202
- *Requires:* `OuterAlloc` shall be constructible from `OuterA2`.
203
-
204
- *Effects:* initializes each allocator within the adaptor with the
205
  corresponding allocator from `other`.
206
 
 
 
 
207
  ``` cpp
208
  template <class OuterA2>
209
  scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2,
210
  InnerAllocs...>&& other) noexcept;
211
  ```
212
 
213
- *Requires:* `OuterAlloc` shall be constructible from `OuterA2`.
214
-
215
- *Effects:* initializes each allocator within the adaptor with the
216
  corresponding allocator rvalue from `other`.
217
 
 
 
 
218
  ### Scoped allocator adaptor members <a id="allocator.adaptor.members">[[allocator.adaptor.members]]</a>
219
 
220
- In the `construct` member functions, *OUTERMOST(x)* is `x` if `x` does
221
  not have an `outer_allocator()` member function and
222
- *OUTERMOST(x.outer_allocator())* otherwise; *OUTERMOST_ALLOC_TRAITS(x)*
223
- is
224
- `allocator_traits<decltype(OUTERMOST(x))>`. *OUTERMOST*(x) and
225
- *OUTERMOST_ALLOC_TRAITS*(x) are recursive operations. It is incumbent
226
- upon the definition of `outer_allocator()` to ensure that the recursion
227
- terminates. It will terminate for all instantiations of
228
- `scoped_allocator_adaptor`.
229
 
230
  ``` cpp
231
  inner_allocator_type& inner_allocator() noexcept;
232
  const inner_allocator_type& inner_allocator() const noexcept;
233
  ```
@@ -263,12 +284,12 @@ pointer allocate(size_type n, const_void_pointer hint);
263
 
264
  ``` cpp
265
  void deallocate(pointer p, size_type n) noexcept;
266
  ```
267
 
268
- *Effects:*
269
- `allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)`;
270
 
271
  ``` cpp
272
  size_type max_size() const;
273
  ```
274
 
@@ -279,124 +300,162 @@ template <class T, class... Args>
279
  void construct(T* p, Args&&... args);
280
  ```
281
 
282
  *Effects:*
283
 
284
- - If `uses_allocator<T, inner_allocator_type>::value` is `false` and
285
- `is_constructible<T, Args...>::value` is `true`, calls
286
- *OUTERMOST_ALLOC_TRAITS*(`*this`)`::construct(`
287
- *`OUTERMOST`*`(*this), p, std::forward<Args>(args)...)`.
288
- - Otherwise, if `uses_allocator<T, inner_allocator_type>::value` is
289
- `true` and
290
- `is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value`
291
- is `true`, calls
292
- *OUTERMOST_ALLOC_TRAITS*(`*this`)`::construct(`*`OUTERMOST`*`(*this), p, allocator_arg,`
293
- `inner_allocator(), std::forward<Args>(args)...)`.
294
- - Otherwise, if `uses_allocator<T, inner_allocator_type>::value` is
295
- `true` and `is_constructible<T, Args..., inner_allocator_type>::value`
296
- is `true`, calls *OUTERMOST_ALLOC_TRAITS*(\*this)::
297
- `construct(`*`OUTERMOST`*`(*this), p, std::forward<Args>(args)...,`
298
- `inner_allocator())`.
299
- - Otherwise, the program is ill-formed. An error will result if
300
- `uses_allocator` evaluates to true but the specific constructor does
301
- not take an allocator. This definition prevents a silent failure to
302
- pass an inner allocator to a contained element.
 
 
 
 
 
 
 
303
 
304
  ``` cpp
305
  template <class T1, class T2, class... Args1, class... Args2>
306
  void construct(pair<T1, T2>* p, piecewise_construct_t,
307
  tuple<Args1...> x, tuple<Args2...> y);
308
  ```
309
 
310
  *Requires:* all of the types in `Args1` and `Args2` shall be
311
- `CopyConstructible` (Table  [[copyconstructible]]).
312
 
313
  *Effects:* Constructs a `tuple` object `xprime` from `x` by the
314
  following rules:
315
 
316
- - If `uses_allocator<T1, inner_allocator_type>::value` is `false` and
317
- `is_constructible<T1, Args1...>::value` is `true`, then `xprime` is
318
- `x`.
319
- - Otherwise, if `uses_allocator<T1, inner_allocator_type>::value` is
320
- `true` and
321
- `is_constructible<T1, allocator_arg_t, inner_allocator_type, Args1...>::value`
322
- is `true`, then `xprime` is
323
- `tuple_cat(tuple<allocator_arg_t, inner_allocator_type&>( allocator_arg, inner_allocator()), std::move(x))`.
324
- - Otherwise, if `uses_allocator<T1, inner_allocator_type>::value` is
325
- `true` and
326
- `is_constructible<T1, Args1..., inner_allocator_type>::value` is
327
- `true`, then `xprime` is
328
- `tuple_cat(std::move(x), tuple<inner_allocator_type&>(inner_allocator()))`.
 
 
 
 
 
329
  - Otherwise, the program is ill-formed.
330
 
331
  and constructs a `tuple` object `yprime` from `y` by the following
332
  rules:
333
 
334
- - If `uses_allocator<T2, inner_allocator_type>::value` is `false` and
335
- `is_constructible<T2, Args2...>::value` is `true`, then `yprime` is
336
- `y`.
337
- - Otherwise, if `uses_allocator<T2, inner_allocator_type>::value` is
338
- `true` and
339
- `is_constructible<T2, allocator_arg_t, inner_allocator_type, Args2...>::value`
340
- is `true`, then `yprime` is
341
- `tuple_cat(tuple<allocator_arg_t, inner_allocator_type&>( allocator_arg, inner_allocator()), std::move(y))`.
342
- - Otherwise, if `uses_allocator<T2, inner_allocator_type>::value` is
343
- `true` and
344
- `is_constructible<T2, Args2..., inner_allocator_type>::value` is
345
- `true`, then `yprime` is
346
- `tuple_cat(std::move(y), tuple<inner_allocator_type&>(inner_allocator()))`.
 
 
 
 
 
347
  - Otherwise, the program is ill-formed.
348
 
349
- then calls
350
- *`OUTERMOST_ALLOC_TRAITS`*`(*this)::construct(`*`OUTERMOST`*`(*this), p,`
351
- `piecewise_construct, std::move(xprime), std::move(yprime))`.
 
 
 
352
 
353
  ``` cpp
354
  template <class T1, class T2>
355
  void construct(pair<T1, T2>* p);
356
  ```
357
 
358
- *Effects:* Equivalent to
359
- `this->construct(p, piecewise_construct, tuple<>(), tuple<>())`.
 
 
 
360
 
361
  ``` cpp
362
  template <class T1, class T2, class U, class V>
363
  void construct(pair<T1, T2>* p, U&& x, V&& y);
364
  ```
365
 
366
- *Effects:* Equivalent to
367
- `this->construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(x)), forward_as_tuple(std::forward<V>(y)))`.
 
 
 
 
 
368
 
369
  ``` cpp
370
  template <class T1, class T2, class U, class V>
371
  void construct(pair<T1, T2>* p, const pair<U, V>& x);
372
  ```
373
 
374
- *Effects:* Equivalent to
375
- `this->construct(p, piecewise_construct, forward_as_tuple(x.first), forward_as_tuple(x.second))`.
 
 
 
 
 
376
 
377
  ``` cpp
378
  template <class T1, class T2, class U, class V>
379
  void construct(pair<T1, T2>* p, pair<U, V>&& x);
380
  ```
381
 
382
- *Effects:* Equivalent to
383
- `this->construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(x.first)), forward_as_tuple(std::forward<V>(x.second)))`.
 
 
 
 
 
384
 
385
  ``` cpp
386
  template <class T>
387
  void destroy(T* p);
388
  ```
389
 
390
- *Effects:* calls
391
- *`OUTERMOST_ALLOC_TRAITS`*`(*this)::destroy(`*`OUTERMOST`*`(*this), p)`.
392
 
393
  ``` cpp
394
  scoped_allocator_adaptor select_on_container_copy_construction() const;
395
  ```
396
 
397
- *Returns:* A new scoped_allocator_adaptor object where each allocator
398
  `A` in the adaptor is initialized from the result of calling
399
  `allocator_traits<A>::select_on_container_copy_construction()` on the
400
  corresponding allocator in `*this`.
401
 
402
  ### Scoped allocator operators <a id="scoped.adaptor.operators">[[scoped.adaptor.operators]]</a>
@@ -405,14 +464,21 @@ corresponding allocator in `*this`.
405
  template <class OuterA1, class OuterA2, class... InnerAllocs>
406
  bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
407
  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
408
  ```
409
 
410
- *Returns:* `a.outer_allocator() == b.outer_allocator()` if
411
- `sizeof...(InnerAllocs)` is zero; otherwise,
412
- `a.outer_allocator() == b.outer_allocator()` `&&`
413
- `a.inner_allocator() == b.inner_allocator()`.
 
 
 
 
 
 
 
414
 
415
  ``` cpp
416
  template <class OuterA1, class OuterA2, class... InnerAllocs>
417
  bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
418
  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
 
29
  allocator is passed to the constructors of the container’s elements,
30
  and, if the elements themselves are containers, the third allocator is
31
  passed to the elements’ elements, and so on. If containers are nested to
32
  a depth greater than the number of allocators, the last allocator is
33
  used repeatedly, as in the single-allocator case, for any remaining
34
+ recursions.
35
+
36
+ [*Note 1*: The `scoped_allocator_adaptor` is derived from the outer
37
  allocator type so it can be substituted for the outer allocator type in
38
+ most expressions. — *end note*]
39
 
40
  ``` cpp
41
  namespace std {
42
  template <class OuterAlloc, class... InnerAllocs>
43
  class scoped_allocator_adaptor : public OuterAlloc {
44
  private:
45
+ using OuterTraits = allocator_traits<OuterAlloc>; // exposition only
46
  scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only
47
  public:
48
+ using outer_allocator_type = OuterAlloc;
49
+ using inner_allocator_type = see below;
50
 
51
+ using value_type = typename OuterTraits::value_type;
52
+ using size_type = typename OuterTraits::size_type;
53
+ using difference_type = typename OuterTraits::difference_type;
54
+ using pointer = typename OuterTraits::pointer;
55
+ using const_pointer = typename OuterTraits::const_pointer;
56
+ using void_pointer = typename OuterTraits::void_pointer;
57
+ using const_void_pointer = typename OuterTraits::const_void_pointer;
58
 
59
+ using propagate_on_container_copy_assignment = see below;
60
+ using propagate_on_container_move_assignment = see below;
61
+ using propagate_on_container_swap = see below;
62
+ using is_always_equal = see below;
63
 
64
  template <class Tp>
65
  struct rebind {
66
+ using other = scoped_allocator_adaptor<
67
+ OuterTraits::template rebind_alloc<Tp>, InnerAllocs...>;
68
  };
69
 
70
  scoped_allocator_adaptor();
71
  template <class OuterA2>
72
  scoped_allocator_adaptor(OuterA2&& outerAlloc,
 
80
  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
81
  template <class OuterA2>
82
  scoped_allocator_adaptor(
83
  scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
84
 
85
+ scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
86
+ scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default;
87
+
88
  ~scoped_allocator_adaptor();
89
 
90
  inner_allocator_type& inner_allocator() noexcept;
91
  const inner_allocator_type& inner_allocator() const noexcept;
92
  outer_allocator_type& outer_allocator() noexcept;
 
115
  void destroy(T* p);
116
 
117
  scoped_allocator_adaptor select_on_container_copy_construction() const;
118
  };
119
 
120
+ template<class OuterAlloc, class... InnerAllocs>
121
+ scoped_allocator_adaptor(OuterAlloc, InnerAllocs...)
122
+ -> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>;
123
+
124
  template <class OuterA1, class OuterA2, class... InnerAllocs>
125
  bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
126
  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
127
  template <class OuterA1, class OuterA2, class... InnerAllocs>
128
  bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
 
131
  ```
132
 
133
  ### Scoped allocator adaptor member types <a id="allocator.adaptor.types">[[allocator.adaptor.types]]</a>
134
 
135
  ``` cpp
136
+ using inner_allocator_type = see below;
137
  ```
138
 
139
  *Type:* `scoped_allocator_adaptor<OuterAlloc>` if
140
  `sizeof...(InnerAllocs)` is zero; otherwise,
141
  `scoped_allocator_adaptor<InnerAllocs...>`.
142
 
143
  ``` cpp
144
+ using propagate_on_container_copy_assignment = see below;
145
  ```
146
 
147
  *Type:* `true_type` if
148
  `allocator_traits<A>::propagate_on_container_copy_assignment::value` is
149
  `true` for any `A` in the set of `OuterAlloc` and `InnerAllocs...`;
150
  otherwise, `false_type`.
151
 
152
  ``` cpp
153
+ using propagate_on_container_move_assignment = see below;
154
  ```
155
 
156
  *Type:* `true_type` if
157
  `allocator_traits<A>::propagate_on_container_move_assignment::value` is
158
  `true` for any `A` in the set of `OuterAlloc` and `InnerAllocs...`;
159
  otherwise, `false_type`.
160
 
161
  ``` cpp
162
+ using propagate_on_container_swap = see below;
163
  ```
164
 
165
  *Type:* `true_type` if
166
  `allocator_traits<A>::propagate_on_container_swap::value` is `true` for
167
  any `A` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise,
168
  `false_type`.
169
 
170
+ ``` cpp
171
+ using is_always_equal = see below;
172
+ ```
173
+
174
+ *Type:* `true_type` if `allocator_traits<A>::is_always_equal::value` is
175
+ `true` for every `A` in the set of `OuterAlloc` and `InnerAllocs...`;
176
+ otherwise, `false_type`.
177
+
178
  ### Scoped allocator adaptor constructors <a id="allocator.adaptor.cnstr">[[allocator.adaptor.cnstr]]</a>
179
 
180
  ``` cpp
181
  scoped_allocator_adaptor();
182
  ```
183
 
184
+ *Effects:* Value-initializes the `OuterAlloc` base class and the `inner`
185
  allocator object.
186
 
187
  ``` cpp
188
  template <class OuterA2>
189
  scoped_allocator_adaptor(OuterA2&& outerAlloc,
190
  const InnerAllocs&... innerAllocs) noexcept;
191
  ```
192
 
193
+ *Effects:* Initializes the `OuterAlloc` base class with
 
 
194
  `std::forward<OuterA2>(outerAlloc)` and `inner` with `innerAllocs...`
195
  (hence recursively initializing each allocator within the adaptor with
196
  the corresponding allocator from the argument list).
197
 
198
+ *Remarks:* This constructor shall not participate in overload resolution
199
+ unless `is_constructible_v<OuterAlloc, OuterA2>` is `true`.
200
+
201
  ``` cpp
202
  scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
203
  ```
204
 
205
+ *Effects:* Initializes each allocator within the adaptor with the
206
  corresponding allocator from `other`.
207
 
208
  ``` cpp
209
  scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
210
  ```
211
 
212
+ *Effects:* Move constructs each allocator within the adaptor with the
213
  corresponding allocator from `other`.
214
 
215
  ``` cpp
216
  template <class OuterA2>
217
  scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2,
218
  InnerAllocs...>& other) noexcept;
219
  ```
220
 
221
+ *Effects:* Initializes each allocator within the adaptor with the
 
 
222
  corresponding allocator from `other`.
223
 
224
+ *Remarks:* This constructor shall not participate in overload resolution
225
+ unless `is_constructible_v<OuterAlloc, const OuterA2&>` is `true`.
226
+
227
  ``` cpp
228
  template <class OuterA2>
229
  scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2,
230
  InnerAllocs...>&& other) noexcept;
231
  ```
232
 
233
+ *Effects:* Initializes each allocator within the adaptor with the
 
 
234
  corresponding allocator rvalue from `other`.
235
 
236
+ *Remarks:* This constructor shall not participate in overload resolution
237
+ unless `is_constructible_v<OuterAlloc, OuterA2>` is `true`.
238
+
239
  ### Scoped allocator adaptor members <a id="allocator.adaptor.members">[[allocator.adaptor.members]]</a>
240
 
241
+ In the `construct` member functions, `OUTERMOST(x)` is `x` if `x` does
242
  not have an `outer_allocator()` member function and
243
+ `OUTERMOST(x.outer_allocator())` otherwise; `OUTERMOST_ALLOC_TRAITS(x)`
244
+ is `allocator_traits<decltype(OUTERMOST(x))>`.
245
+
246
+ [*Note 1*: `OUTERMOST(x)` and `OUTERMOST_ALLOC_TRAITS(x)` are recursive
247
+ operations. It is incumbent upon the definition of `outer_allocator()`
248
+ to ensure that the recursion terminates. It will terminate for all
249
+ instantiations of `scoped_allocator_adaptor`. — *end note*]
250
 
251
  ``` cpp
252
  inner_allocator_type& inner_allocator() noexcept;
253
  const inner_allocator_type& inner_allocator() const noexcept;
254
  ```
 
284
 
285
  ``` cpp
286
  void deallocate(pointer p, size_type n) noexcept;
287
  ```
288
 
289
+ *Effects:* As if by:
290
+ `allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n);`
291
 
292
  ``` cpp
293
  size_type max_size() const;
294
  ```
295
 
 
300
  void construct(T* p, Args&&... args);
301
  ```
302
 
303
  *Effects:*
304
 
305
+ - If `uses_allocator_v<T, inner_allocator_type>` is `false` and
306
+ `is_constructible_v<T,`
307
+ `Args...>` is `true`, calls:
308
+ ``` cpp
309
+ OUTERMOST_ALLOC_TRAITS(*this)::construct(
310
+ OUTERMOST(*this), p, std::forward<Args>(args)...)
311
+ ```
312
+ - Otherwise, if `uses_allocator_v<T, inner_allocator_type>` is `true`
313
+ and
314
+ `is_constructible_v<T, allocator_arg_t, inner_allocator_type&, Args...>`
315
+ is `true`, calls:
316
+ ``` cpp
317
+ OUTERMOST_ALLOC_TRAITS(*this)::construct(
318
+ OUTERMOST(*this), p, allocator_arg, inner_allocator(), std::forward<Args>(args)...)
319
+ ```
320
+ - Otherwise, if `uses_allocator_v<T, inner_allocator_type>` is `true`
321
+ and `is_constructible_v<T, Args..., inner_allocator_type&>` is `true`,
322
+ calls:
323
+ ``` cpp
324
+ OUTERMOST_ALLOC_TRAITS(*this)::construct(
325
+ OUTERMOST(*this), p, std::forward<Args>(args)..., inner_allocator())
326
+ ```
327
+ - Otherwise, the program is ill-formed. \[*Note 2*: An error will result
328
+ if `uses_allocator` evaluates to `true` but the specific constructor
329
+ does not take an allocator. This definition prevents a silent failure
330
+ to pass an inner allocator to a contained element. — *end note*]
331
 
332
  ``` cpp
333
  template <class T1, class T2, class... Args1, class... Args2>
334
  void construct(pair<T1, T2>* p, piecewise_construct_t,
335
  tuple<Args1...> x, tuple<Args2...> y);
336
  ```
337
 
338
  *Requires:* all of the types in `Args1` and `Args2` shall be
339
+ `CopyConstructible` (Table  [[tab:copyconstructible]]).
340
 
341
  *Effects:* Constructs a `tuple` object `xprime` from `x` by the
342
  following rules:
343
 
344
+ - If `uses_allocator_v<T1, inner_allocator_type>` is `false` and
345
+ `is_constructible_v<T1,`
346
+ `Args1...>` is `true`, then `xprime` is `x`.
347
+ - Otherwise, if `uses_allocator_v<T1, inner_allocator_type>` is `true`
348
+ and
349
+ `is_constructible_v<T1, allocator_arg_t, inner_allocator_type&, Args1...>`
350
+ is `true`, then `xprime` is:
351
+ ``` cpp
352
+ tuple_cat(
353
+ tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()),
354
+ std::move(x))
355
+ ```
356
+ - Otherwise, if `uses_allocator_v<T1, inner_allocator_type>` is `true`
357
+ and `is_constructible_v<T1, Args1..., inner_allocator_type&>` is
358
+ `true`, then `xprime` is:
359
+ ``` cpp
360
+ tuple_cat(std::move(x), tuple<inner_allocator_type&>(inner_allocator()))
361
+ ```
362
  - Otherwise, the program is ill-formed.
363
 
364
  and constructs a `tuple` object `yprime` from `y` by the following
365
  rules:
366
 
367
+ - If `uses_allocator_v<T2, inner_allocator_type>` is `false` and
368
+ `is_constructible_v<T2,`
369
+ `Args2...>` is `true`, then `yprime` is `y`.
370
+ - Otherwise, if `uses_allocator_v<T2, inner_allocator_type>` is `true`
371
+ and
372
+ `is_constructible_v<T2, allocator_arg_t, inner_allocator_type&, Args2...>`
373
+ is `true`, then `yprime` is:
374
+ ``` cpp
375
+ tuple_cat(
376
+ tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()),
377
+ std::move(y))
378
+ ```
379
+ - Otherwise, if `uses_allocator_v<T2, inner_allocator_type>` is `true`
380
+ and `is_constructible_v<T2, Args2..., inner_allocator_type&>` is
381
+ `true`, then `yprime` is:
382
+ ``` cpp
383
+ tuple_cat(std::move(y), tuple<inner_allocator_type&>(inner_allocator()))
384
+ ```
385
  - Otherwise, the program is ill-formed.
386
 
387
+ then calls:
388
+
389
+ ``` cpp
390
+ OUTERMOST_ALLOC_TRAITS(*this)::construct(
391
+ OUTERMOST(*this), p, piecewise_construct, std::move(xprime), std::move(yprime))
392
+ ```
393
 
394
  ``` cpp
395
  template <class T1, class T2>
396
  void construct(pair<T1, T2>* p);
397
  ```
398
 
399
+ *Effects:* Equivalent to:
400
+
401
+ ``` cpp
402
+ construct(p, piecewise_construct, tuple<>(), tuple<>());
403
+ ```
404
 
405
  ``` cpp
406
  template <class T1, class T2, class U, class V>
407
  void construct(pair<T1, T2>* p, U&& x, V&& y);
408
  ```
409
 
410
+ *Effects:* Equivalent to:
411
+
412
+ ``` cpp
413
+ construct(p, piecewise_construct,
414
+ forward_as_tuple(std::forward<U>(x)),
415
+ forward_as_tuple(std::forward<V>(y)));
416
+ ```
417
 
418
  ``` cpp
419
  template <class T1, class T2, class U, class V>
420
  void construct(pair<T1, T2>* p, const pair<U, V>& x);
421
  ```
422
 
423
+ *Effects:* Equivalent to:
424
+
425
+ ``` cpp
426
+ construct(p, piecewise_construct,
427
+ forward_as_tuple(x.first),
428
+ forward_as_tuple(x.second));
429
+ ```
430
 
431
  ``` cpp
432
  template <class T1, class T2, class U, class V>
433
  void construct(pair<T1, T2>* p, pair<U, V>&& x);
434
  ```
435
 
436
+ *Effects:* Equivalent to:
437
+
438
+ ``` cpp
439
+ construct(p, piecewise_construct,
440
+ forward_as_tuple(std::forward<U>(x.first)),
441
+ forward_as_tuple(std::forward<V>(x.second)));
442
+ ```
443
 
444
  ``` cpp
445
  template <class T>
446
  void destroy(T* p);
447
  ```
448
 
449
+ *Effects:* Calls
450
+ *OUTERMOST_ALLOC_TRAITS*(\*this)::destroy(*OUTERMOST*(\*this), p).
451
 
452
  ``` cpp
453
  scoped_allocator_adaptor select_on_container_copy_construction() const;
454
  ```
455
 
456
+ *Returns:* A new `scoped_allocator_adaptor` object where each allocator
457
  `A` in the adaptor is initialized from the result of calling
458
  `allocator_traits<A>::select_on_container_copy_construction()` on the
459
  corresponding allocator in `*this`.
460
 
461
  ### Scoped allocator operators <a id="scoped.adaptor.operators">[[scoped.adaptor.operators]]</a>
 
464
  template <class OuterA1, class OuterA2, class... InnerAllocs>
465
  bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
466
  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
467
  ```
468
 
469
+ *Returns:* If `sizeof...(InnerAllocs)` is zero,
470
+
471
+ ``` cpp
472
+ a.outer_allocator() == b.outer_allocator()
473
+ ```
474
+
475
+ otherwise
476
+
477
+ ``` cpp
478
+ a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator()
479
+ ```
480
 
481
  ``` cpp
482
  template <class OuterA1, class OuterA2, class... InnerAllocs>
483
  bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
484
  const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;