From Jason Turner

[mem.poly.allocator.class]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmplznnwyvm/{from.md → to.md} +112 -149
tmp/tmplznnwyvm/{from.md → to.md} RENAMED
@@ -1,19 +1,23 @@
1
  ### Class template `polymorphic_allocator` <a id="mem.poly.allocator.class">[[mem.poly.allocator.class]]</a>
2
 
3
- A specialization of class template `pmr::polymorphic_allocator` conforms
4
- to the `Allocator` requirements ([[allocator.requirements]]).
5
- Constructed with different memory resources, different instances of the
6
- same specialization of `pmr::polymorphic_allocator` can exhibit entirely
7
  different allocation behavior. This runtime polymorphism allows objects
8
  that use `polymorphic_allocator` to behave as if they used different
9
  allocator types at run time even though they use the same static
10
  allocator type.
11
 
 
 
 
 
12
  ``` cpp
13
- template <class Tp>
14
- class polymorphic_allocator {
15
  memory_resource* memory_rsrc; // exposition only
16
 
17
  public:
18
  using value_type = Tp;
19
 
@@ -24,42 +28,37 @@ public:
24
  polymorphic_allocator(const polymorphic_allocator& other) = default;
25
 
26
  template<class U>
27
  polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
28
 
29
- polymorphic_allocator&
30
- operator=(const polymorphic_allocator& rhs) = delete;
31
 
32
  // [mem.poly.allocator.mem], member functions
33
- Tp* allocate(size_t n);
34
  void deallocate(Tp* p, size_t n);
35
 
 
 
 
 
 
 
 
36
  template<class T, class... Args>
37
  void construct(T* p, Args&&... args);
38
 
39
- template <class T1, class T2, class... Args1, class... Args2>
40
- void construct(pair<T1,T2>* p, piecewise_construct_t,
41
- tuple<Args1...> x, tuple<Args2...> y);
42
- template <class T1, class T2>
43
- void construct(pair<T1,T2>* p);
44
- template <class T1, class T2, class U, class V>
45
- void construct(pair<T1,T2>* p, U&& x, V&& y);
46
- template <class T1, class T2, class U, class V>
47
- void construct(pair<T1,T2>* p, const pair<U, V>& pr);
48
- template <class T1, class T2, class U, class V>
49
- void construct(pair<T1,T2>* p, pair<U, V>&& pr);
50
-
51
  template<class T>
52
  void destroy(T* p);
53
 
54
  polymorphic_allocator select_on_container_copy_construction() const;
55
 
56
  memory_resource* resource() const;
57
  };
 
58
  ```
59
 
60
- #### `polymorphic_allocator` constructors <a id="mem.poly.allocator.ctor">[[mem.poly.allocator.ctor]]</a>
61
 
62
  ``` cpp
63
  polymorphic_allocator() noexcept;
64
  ```
65
 
@@ -67,171 +66,143 @@ polymorphic_allocator() noexcept;
67
 
68
  ``` cpp
69
  polymorphic_allocator(memory_resource* r);
70
  ```
71
 
72
- *Requires:* `r` is non-null.
73
 
74
  *Effects:* Sets `memory_rsrc` to `r`.
75
 
76
  *Throws:* Nothing.
77
 
78
  [*Note 1*: This constructor provides an implicit conversion from
79
  `memory_resource*`. — *end note*]
80
 
81
  ``` cpp
82
- template <class U>
83
- polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
84
  ```
85
 
86
  *Effects:* Sets `memory_rsrc` to `other.resource()`.
87
 
88
- #### `polymorphic_allocator` member functions <a id="mem.poly.allocator.mem">[[mem.poly.allocator.mem]]</a>
89
 
90
  ``` cpp
91
- Tp* allocate(size_t n);
92
  ```
93
 
94
- *Returns:* Equivalent to
 
95
 
96
  ``` cpp
97
  return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
98
  ```
99
 
100
  ``` cpp
101
  void deallocate(Tp* p, size_t n);
102
  ```
103
 
104
- *Requires:* `p` was allocated from a memory resource `x`, equal to
105
  `*memory_rsrc`, using `x.allocate(n * sizeof(Tp), alignof(Tp))`.
106
 
107
  *Effects:* Equivalent to
108
  `memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))`.
109
 
110
  *Throws:* Nothing.
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  ``` cpp
113
  template<class T, class... Args>
114
  void construct(T* p, Args&&... args);
115
  ```
116
 
117
- *Requires:* Uses-allocator construction of `T` with allocator
118
- `resource()` (see  [[allocator.uses.construction]]) and constructor
119
- arguments `std::forward<Args>(args)...` is well-formed.
120
-
121
- [*Note 1*: Uses-allocator construction is always well formed for types
122
- that do not use allocators. — *end note*]
123
 
124
  *Effects:* Construct a `T` object in the storage whose address is
125
- represented by `p` by uses-allocator construction with allocator
126
- `resource()` and constructor arguments `std::forward<Args>(args)...`.
127
 
128
  *Throws:* Nothing unless the constructor for `T` throws.
129
 
130
- ``` cpp
131
- template <class T1, class T2, class... Args1, class... Args2>
132
- void construct(pair<T1,T2>* p, piecewise_construct_t,
133
- tuple<Args1...> x, tuple<Args2...> y);
134
- ```
135
-
136
- [*Note 2*: This method and the `construct` methods that follow are
137
- overloads for piecewise construction of
138
- pairs ([[pairs.pair]]). — *end note*]
139
-
140
- *Effects:* Let `xprime` be a `tuple` constructed from `x` according to
141
- the appropriate rule from the following list.
142
-
143
- [*Note 3*: The following description can be summarized as constructing
144
- a `pair<T1, T2>` object in the storage whose address is represented by
145
- `p`, as if by separate uses-allocator construction with allocator
146
- `resource()` ([[allocator.uses.construction]]) of `p->first` using the
147
- elements of `x` and `p->second` using the elements of
148
- `y`. — *end note*]
149
-
150
- - If `uses_allocator_v<T1,memory_resource*>` is `false`
151
- and `is_constructible_v<T1,Args1...>` is `true`,
152
- then `xprime` is `x`.
153
- - Otherwise, if `uses_allocator_v<T1,memory_resource*>` is `true`
154
- and `is_constructible_v<T1,allocator_arg_t,memory_resource*,Args1...>`
155
- is `true`,
156
- then `xprime` is
157
- `tuple_cat(make_tuple(allocator_arg, resource()), std::move(x))`.
158
- - Otherwise, if `uses_allocator_v<T1,memory_resource*>` is `true`
159
- and `is_constructible_v<T1,Args1...,memory_resource*>` is `true`,
160
- then `xprime` is `tuple_cat(std::move(x), make_tuple(resource()))`.
161
- - Otherwise the program is ill formed.
162
-
163
- Let `yprime` be a tuple constructed from `y` according to the
164
- appropriate rule from the following list:
165
-
166
- - If `uses_allocator_v<T2,memory_resource*>` is `false`
167
- and `is_constructible_v<T2,Args2...>` is `true`,
168
- then `yprime` is `y`.
169
- - Otherwise, if `uses_allocator_v<T2,memory_resource*>` is `true`
170
- and `is_constructible_v<T2,allocator_arg_t,memory_resource*,Args2...>`
171
- is `true`,
172
- then `yprime` is
173
- `tuple_cat(make_tuple(allocator_arg, resource()), std::move(y))`.
174
- - Otherwise, if `uses_allocator_v<T2,memory_resource*>` is `true`
175
- and `is_constructible_v<T2,Args2...,memory_resource*>` is `true`,
176
- then `yprime` is `tuple_cat(std::move(y), make_tuple(resource()))`.
177
- - Otherwise the program is ill formed.
178
-
179
- Then, using `piecewise_construct`, `xprime`, and `yprime` as the
180
- constructor arguments, this function constructs a `pair<T1, T2>` object
181
- in the storage whose address is represented by `p`.
182
-
183
- ``` cpp
184
- template <class T1, class T2>
185
- void construct(pair<T1,T2>* p);
186
- ```
187
-
188
- *Effects:* Equivalent to:
189
-
190
- ``` cpp
191
- construct(p, piecewise_construct, tuple<>(), tuple<>());
192
- ```
193
-
194
- ``` cpp
195
- template <class T1, class T2, class U, class V>
196
- void construct(pair<T1,T2>* p, U&& x, V&& y);
197
- ```
198
-
199
- *Effects:* Equivalent to:
200
-
201
- ``` cpp
202
- construct(p, piecewise_construct,
203
- forward_as_tuple(std::forward<U>(x)),
204
- forward_as_tuple(std::forward<V>(y)));
205
- ```
206
-
207
- ``` cpp
208
- template <class T1, class T2, class U, class V>
209
- void construct(pair<T1,T2>* p, const pair<U, V>& pr);
210
- ```
211
-
212
- *Effects:* Equivalent to:
213
-
214
- ``` cpp
215
- construct(p, piecewise_construct,
216
- forward_as_tuple(pr.first),
217
- forward_as_tuple(pr.second));
218
- ```
219
-
220
- ``` cpp
221
- template <class T1, class T2, class U, class V>
222
- void construct(pair<T1,T2>* p, pair<U, V>&& pr);
223
- ```
224
-
225
- *Effects:* Equivalent to:
226
-
227
- ``` cpp
228
- construct(p, piecewise_construct,
229
- forward_as_tuple(std::forward<U>(pr.first)),
230
- forward_as_tuple(std::forward<V>(pr.second)));
231
- ```
232
-
233
  ``` cpp
234
  template<class T>
235
  void destroy(T* p);
236
  ```
237
 
@@ -249,23 +220,15 @@ polymorphic_allocator select_on_container_copy_construction() const;
249
  memory_resource* resource() const;
250
  ```
251
 
252
  *Returns:* `memory_rsrc`.
253
 
254
- #### `polymorphic_allocator` equality <a id="mem.poly.allocator.eq">[[mem.poly.allocator.eq]]</a>
255
 
256
  ``` cpp
257
  template<class T1, class T2>
258
  bool operator==(const polymorphic_allocator<T1>& a,
259
  const polymorphic_allocator<T2>& b) noexcept;
260
  ```
261
 
262
  *Returns:* `*a.resource() == *b.resource()`.
263
 
264
- ``` cpp
265
- template <class T1, class T2>
266
- bool operator!=(const polymorphic_allocator<T1>& a,
267
- const polymorphic_allocator<T2>& b) noexcept;
268
- ```
269
-
270
- *Returns:* `!(a == b)`.
271
-
 
1
  ### Class template `polymorphic_allocator` <a id="mem.poly.allocator.class">[[mem.poly.allocator.class]]</a>
2
 
3
+ A specialization of class template `pmr::polymorphic_allocator` meets
4
+ the *Cpp17Allocator* requirements ([[cpp17.allocator]]). Constructed
5
+ with different memory resources, different instances of the same
6
+ specialization of `pmr::polymorphic_allocator` can exhibit entirely
7
  different allocation behavior. This runtime polymorphism allows objects
8
  that use `polymorphic_allocator` to behave as if they used different
9
  allocator types at run time even though they use the same static
10
  allocator type.
11
 
12
+ All specializations of class template `pmr::polymorphic_allocator` meet
13
+ the allocator completeness requirements
14
+ [[allocator.requirements.completeness]].
15
+
16
  ``` cpp
17
+ namespace std::pmr {
18
+ template<class Tp = byte> class polymorphic_allocator {
19
  memory_resource* memory_rsrc; // exposition only
20
 
21
  public:
22
  using value_type = Tp;
23
 
 
28
  polymorphic_allocator(const polymorphic_allocator& other) = default;
29
 
30
  template<class U>
31
  polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
32
 
33
+ polymorphic_allocator& operator=(const polymorphic_allocator&) = delete;
 
34
 
35
  // [mem.poly.allocator.mem], member functions
36
+ [[nodiscard]] Tp* allocate(size_t n);
37
  void deallocate(Tp* p, size_t n);
38
 
39
+ [[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t));
40
+ void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t));
41
+ template<class T> [[nodiscard]] T* allocate_object(size_t n = 1);
42
+ template<class T> void deallocate_object(T* p, size_t n = 1);
43
+ template<class T, class... CtorArgs> [[nodiscard]] T* new_object(CtorArgs&&... ctor_args);
44
+ template<class T> void delete_object(T* p);
45
+
46
  template<class T, class... Args>
47
  void construct(T* p, Args&&... args);
48
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  template<class T>
50
  void destroy(T* p);
51
 
52
  polymorphic_allocator select_on_container_copy_construction() const;
53
 
54
  memory_resource* resource() const;
55
  };
56
+ }
57
  ```
58
 
59
+ #### Constructors <a id="mem.poly.allocator.ctor">[[mem.poly.allocator.ctor]]</a>
60
 
61
  ``` cpp
62
  polymorphic_allocator() noexcept;
63
  ```
64
 
 
66
 
67
  ``` cpp
68
  polymorphic_allocator(memory_resource* r);
69
  ```
70
 
71
+ *Preconditions:* `r` is non-null.
72
 
73
  *Effects:* Sets `memory_rsrc` to `r`.
74
 
75
  *Throws:* Nothing.
76
 
77
  [*Note 1*: This constructor provides an implicit conversion from
78
  `memory_resource*`. — *end note*]
79
 
80
  ``` cpp
81
+ template<class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
 
82
  ```
83
 
84
  *Effects:* Sets `memory_rsrc` to `other.resource()`.
85
 
86
+ #### Member functions <a id="mem.poly.allocator.mem">[[mem.poly.allocator.mem]]</a>
87
 
88
  ``` cpp
89
+ [[nodiscard]] Tp* allocate(size_t n);
90
  ```
91
 
92
+ *Effects:* If `numeric_limits<size_t>::max() / sizeof(Tp) < n`, throws
93
+ `bad_array_new_length`. Otherwise equivalent to:
94
 
95
  ``` cpp
96
  return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
97
  ```
98
 
99
  ``` cpp
100
  void deallocate(Tp* p, size_t n);
101
  ```
102
 
103
+ *Preconditions:* `p` was allocated from a memory resource `x`, equal to
104
  `*memory_rsrc`, using `x.allocate(n * sizeof(Tp), alignof(Tp))`.
105
 
106
  *Effects:* Equivalent to
107
  `memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))`.
108
 
109
  *Throws:* Nothing.
110
 
111
+ ``` cpp
112
+ [[nodiscard]] void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t));
113
+ ```
114
+
115
+ *Effects:* Equivalent to:
116
+ `return memory_rsrc->allocate(nbytes, alignment);`
117
+
118
+ [*Note 1*: The return type is `void*` (rather than, e.g., `byte*`) to
119
+ support conversion to an arbitrary pointer type `U*` by
120
+ `static_cast<U*>`, thus facilitating construction of a `U` object in the
121
+ allocated memory. — *end note*]
122
+
123
+ ``` cpp
124
+ void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t));
125
+ ```
126
+
127
+ *Effects:* Equivalent to
128
+ `memory_rsrc->deallocate(p, nbytes, alignment)`.
129
+
130
+ ``` cpp
131
+ template<class T>
132
+ [[nodiscard]] T* allocate_object(size_t n = 1);
133
+ ```
134
+
135
+ *Effects:* Allocates memory suitable for holding an array of `n` objects
136
+ of type `T`, as follows:
137
+
138
+ - if `numeric_limits<size_t>::max() / sizeof(T) < n`, throws
139
+ `bad_array_new_length`,
140
+ - otherwise equivalent to:
141
+ ``` cpp
142
+ return static_cast<T*>(allocate_bytes(n*sizeof(T), alignof(T)));
143
+ ```
144
+
145
+ [*Note 2*: `T` is not deduced and must therefore be provided as a
146
+ template argument. — *end note*]
147
+
148
+ ``` cpp
149
+ template<class T>
150
+ void deallocate_object(T* p, size_t n = 1);
151
+ ```
152
+
153
+ *Effects:* Equivalent to `deallocate_bytes(p, n*sizeof(T), alignof(T))`.
154
+
155
+ ``` cpp
156
+ template<class T, class CtorArgs...>
157
+ [[nodiscard]] T* new_object(CtorArgs&&... ctor_args);
158
+ ```
159
+
160
+ *Effects:* Allocates and constructs an object of type `T`, as follows.
161
+ Equivalent to:
162
+
163
+ ``` cpp
164
+ T* p = allocate_object<T>();
165
+ try {
166
+ construct(p, std::forward<CtorArgs>(ctor_args)...);
167
+ } catch (...) {
168
+ deallocate_object(p);
169
+ throw;
170
+ }
171
+ return p;
172
+ ```
173
+
174
+ [*Note 3*: `T` is not deduced and must therefore be provided as a
175
+ template argument. — *end note*]
176
+
177
+ ``` cpp
178
+ template<class T>
179
+ void delete_object(T* p);
180
+ ```
181
+
182
+ *Effects:* Equivalent to:
183
+
184
+ ``` cpp
185
+ destroy(p);
186
+ deallocate_object(p);
187
+ ```
188
+
189
  ``` cpp
190
  template<class T, class... Args>
191
  void construct(T* p, Args&&... args);
192
  ```
193
 
194
+ *Mandates:* Uses-allocator construction of `T` with allocator `*this`
195
+ (see  [[allocator.uses.construction]]) and constructor arguments
196
+ `std::forward<Args>(args)...` is well-formed.
 
 
 
197
 
198
  *Effects:* Construct a `T` object in the storage whose address is
199
+ represented by `p` by uses-allocator construction with allocator `*this`
200
+ and constructor arguments `std::forward<Args>(args)...`.
201
 
202
  *Throws:* Nothing unless the constructor for `T` throws.
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  ``` cpp
205
  template<class T>
206
  void destroy(T* p);
207
  ```
208
 
 
220
  memory_resource* resource() const;
221
  ```
222
 
223
  *Returns:* `memory_rsrc`.
224
 
225
+ #### Equality <a id="mem.poly.allocator.eq">[[mem.poly.allocator.eq]]</a>
226
 
227
  ``` cpp
228
  template<class T1, class T2>
229
  bool operator==(const polymorphic_allocator<T1>& a,
230
  const polymorphic_allocator<T2>& b) noexcept;
231
  ```
232
 
233
  *Returns:* `*a.resource() == *b.resource()`.
234