• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1////
2Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com)
3
4Distributed under the Boost Software License, Version 1.0.
5
6See accompanying file LICENSE_1_0.txt or copy at
7http://www.boost.org/LICENSE_1_0.txt
8////
9
10[#allocate_unique]
11# allocate_unique: Creating unique_ptr
12:toc:
13:toc-title:
14:idprefix: allocate_unique_
15
16## Description
17
18The `allocate_unique` family of function templates provide convenient and safe
19ways to obtain a `std::unique_ptr` that manages a new object created using an
20allocator.
21
22## Rationale
23
24The {cpp}14 standard introduced `std::make_unique` which used operator `new` to
25create new objects. However, there is no convenient facility in the standard
26library to use an allocator for the creation of the objects managed by
27`std::unique_ptr`. Users writing allocator aware code have often requested an
28`allocate_unique` factory function. This function is to `std::unique_ptr` what
29`std::allocate_shared` is to `std::shared_ptr`.
30
31## Synopsis
32
33`allocate_unique` is defined in `<boost/smart_ptr/allocate_unique.hpp>`.
34
35[subs=+quotes]
36```
37namespace boost {
38  template<class T, class A>
39  class alloc_deleter;
40
41  template<class T, class A>
42  using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A>>;
43
44  `// T is not an array`
45  template<class T, class A, class... Args>
46    std::unique_ptr<T, alloc_deleter<T, A>>
47      allocate_unique(const A& a, Args&&... args);
48
49  `// T is not an array`
50  template<class T, class A>
51    std::unique_ptr<T, alloc_deleter<T, A>>
52      allocate_unique(const A& a, type_identity_t<T>&& v);
53
54  `// T is an array of unknown bounds`
55  template<class T, class A>
56    std::unique_ptr<T, alloc_deleter<T, A>>
57      allocate_unique(const A& a, std::size_t n);
58
59  `// T is an array of known bounds`
60  template<class T, class A>
61    std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
62      allocate_unique(const A& a);
63
64  `// T is an array of unknown bounds`
65  template<class T, class A>
66    std::unique_ptr<T, alloc_deleter<T, A>>
67      allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v);
68
69  `// T is an array of known bounds`
70  template<class T, class A>
71    std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
72      allocate_unique(const A& a, const remove_extent_t<T>& v);
73
74  `// T is not an array`
75  template<class T, class A>
76    std::unique_ptr<T, alloc_noinit_deleter<T, A>>
77      allocate_unique_noinit(const A& a);
78
79  `// T is an array of unknown bounds`
80  template<class T, class A>
81    std::unique_ptr<T, alloc_noinit_deleter<T, A>>
82      allocate_unique_noinit(const A& a, std::size_t n);
83
84  `// T is an array of known bounds`
85  template<class T, class A>
86    std::unique_ptr<remove_extent_t<T>[], alloc_noinit_deleter<T, A>>
87      allocate_unique_noinit(const A& a);
88}
89```
90
91## Common Requirements
92
93The common requirements that apply to all `allocate_unique` and
94`allocate_unique_noinit` overloads, unless specified otherwise, are described
95below.
96
97Requires:: `A` shall be an _allocator_. The copy constructor and destructor
98of `A` shall not throw exceptions.
99
100Effects:: Allocates memory for an object of type `T` or `n` objects of `U`
101(if `T` is an array type of the form `U[]` and  `n` is determined by
102arguments, as specified by the concrete overload). The object is initialized
103from arguments as specified by the concrete overload. Uses a rebound copy of
104`a` (for an unspecified `value_type`) to allocate memory. If an exception is
105thrown, the functions have no effect.
106
107Returns:: A `std::unique_ptr` instance that stores and owns the address of the
108newly constructed object.
109
110Postconditions:: `r.get() != 0`, where `r` is the return value.
111
112Throws:: An exception thrown from `A::allocate`, or from the initialization of
113the object.
114
115Remarks::
116* When an object of an array type is specified to be initialized to a value of
117the same type `v`, this shall be interpreted to mean that each array element
118of the object is initialized to the corresponding element from `v`.
119* When an object of an array type is specified to be value-initialized, this
120shall be interpreted to mean that each array element of the object is
121value-initialized.
122* When a (sub)object of non-array type `U` is specified to be initialized to a
123value `v`, or constructed from `args\...`, `allocate_unique` shall perform this
124initialization via the expression
125`std::allocator_traits<A2>::construct(a2, p, expr)` (where `_expr_` is `v` or
126`std::forward<Args>(args)\...)` respectively), `p` points to storage suitable
127to hold an object of type `U`, and `a2` of type `A2` is a potentially rebound
128copy of `a`.
129* When a (sub)object of non-array type `U` is specified to be
130default-initialized, `allocate_unique_noinit` shall perform this initialization
131via the expression `::new(p) U`, where `p` has type `void*` and points to
132storage suitable to hold an object of type `U`.
133* When a (sub)object of non-array type `U` is specified to be
134value-initialized, `allocate_unique` shall perform this initialization via the
135expression `std::allocator_traits<A2>::construct(a2, p)`, where `p` points to
136storage suitable to hold an object of type `U` and `a2` of type `A2` is a
137potentially rebound copy of `a`.
138* Array elements are initialized in ascending order of their addresses.
139* When the lifetime of the object managed by the return value ends, or when the
140initialization of an array element throws an exception, the initialized
141elements should be destroyed in the reverse order of their construction.
142
143## Free Functions
144
145```
146template<class T, class A, class... Args>
147  std::unique_ptr<T, alloc_deleter<T, A>>
148    allocate_unique(const A& a, Args&&... args);
149```
150[none]
151* {blank}
152+
153Constraints:: `T` is not an array.
154Returns:: A `std::unique_ptr` to an object of type `T`, constructed from
155`args\...`.
156Examples::
157* `auto p = allocate_unique<int>(a);`
158* `auto p = allocate_unique<std::vector<int>>(a, 16, 1);`
159
160```
161template<class T, class A>
162  std::unique_ptr<T, alloc_deleter<T, A>>
163    allocate_unique(const A& a, type_identity_t<T>&& v);
164```
165[none]
166* {blank}
167+
168Constraints:: `T` is not an array.
169Returns:: A `std::unique_ptr` to an object of type `T`, constructed from `v`.
170Example:: `auto p = allocate_unique<std::vector<int>>(a, {1, 2});`
171
172```
173template<class T, class A>
174  std::unique_ptr<T, alloc_deleter<T, A>>
175    allocate_unique(const A& a, std::size_t n);
176```
177[none]
178* {blank}
179+
180Constraints:: `T` is an array of unknown bounds.
181Returns:: A `std::unique_ptr` to a sequence of `n` value-initialized objects of
182type `remove_extent_t<T>`.
183Examples::
184* `auto p = allocate_unique<double[]>(a, 1024);`
185* `auto p = allocate_unique<double[][2][2]>(a, 6);`
186
187```
188template<class T, class A>
189  std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
190    allocate_unique(const A& a);
191```
192[none]
193* {blank}
194+
195Constraints:: `T` is an array of known bounds.
196Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` value-initialized
197objects of type `remove_extent_t<T>`.
198Examples::
199* `auto p = allocate_unique<double[1024]>(a);`
200* `auto p = allocate_unique<double[6][2][2]>(a);`
201
202```
203template<class T, class A>
204  std::unique_ptr<T, alloc_deleter<T, A>>
205    allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v);
206```
207[none]
208* {blank}
209+
210Constraints:: `T` is an array of unknown bounds.
211Returns:: A `std::unique_ptr` to a sequence of `n` objects of type
212`remove_extent_t<T>`, each initialized to `v`.
213Examples::
214* `auto p = allocate_unique<double[]>(a, 1024, 1.0);`
215* `auto p = allocate_unique<double[][2]>(a, 6, {1.0, 0.0});`
216* `auto p = allocate_unique<std::vector<int>[]>(a, 4, {1, 2});`
217
218```
219template<class T, class A>
220  std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
221    allocate_unique(const A& a, const remove_extent_t<T>& v);
222```
223[none]
224* {blank}
225+
226Constraints:: `T` is an array of known bounds.
227Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` objects of type
228`remove_extent_t<T>`, each initialized to `v`.
229Examples::
230* `auto p = allocate_unique<double[1024]>(a, 1.0);`
231* `auto p = allocate_unique<double[6][2]>(a, {1.0, 0.0});`
232* `auto p = allocate_unique<std::vector<int>[4]>(a, {1, 2});`
233
234```
235template<class T, class A>
236  std::unique_ptr<T, alloc_noinit_deleter<T, A>>
237    allocate_unique_noinit(const A& a);
238```
239[none]
240* {blank}
241+
242Constraints:: `T` is not an array.
243Returns:: A `std::unique_ptr` to a default-initialized object of type `T`.
244Example:: `auto p = allocate_unique_noinit<double>(a);`
245
246```
247template<class T, class A>
248  std::unique_ptr<T, alloc_noinit_deleter<T, A>>
249    allocate_unique_noinit(const A& a, std::size_t n);
250```
251[none]
252* {blank}
253+
254Constraints:: `T` is an array of unknown bounds.
255Returns:: A `std::unique_ptr` to a sequence of `n` default-initialized objects
256of type `remove_extent_t<T>`.
257Example:: `auto p = allocate_unique_noinit<double[]>(a, 1024);`
258
259```
260template<class T, class A>
261  std::unique_ptr<remove_extent_t<T>, alloc_noinit_deleter<T, A>>
262    allocate_unique_noinit(const A& a);
263```
264[none]
265* {blank}
266+
267Constraints:: `T` is an array of known bounds.
268Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>`
269default-initialized objects of type `remove_extent_t<T>`.
270Example:: `auto p = allocate_unique_noinit<double[1024]>(a);`
271
272## Deleter
273
274Class template `alloc_deleter` is the deleter used by the `allocate_unique`
275functions.
276
277### Synopsis
278
279[subs=+quotes]
280```
281template<class T, class A>
282class alloc_deleter {
283public:
284  using pointer = `unspecified`;
285
286  explicit alloc_deleter(const A& a) noexcept;
287
288  void operator()(pointer p);
289};
290```
291
292### Members
293
294[subs=+quotes]
295```
296using pointer = `unspecified`;
297```
298[none]
299* {blank}
300+
301A type that satisfies _NullablePointer_.
302
303```
304explicit alloc_deleter(const A& a) noexcept;
305```
306[none]
307* {blank}
308+
309Effects:: Initializes the stored allocator from `a`.
310
311```
312void operator()(pointer p);
313```
314[none]
315* {blank}
316+
317Effects:: Destroys the objects and deallocates the storage referenced by `p`,
318using the stored allocator.
319