2 Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com)
4 Distributed under the Boost Software License, Version 1.0.
6 See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt
11 # allocate_unique: Creating unique_ptr
14 :idprefix: allocate_unique_
18 The `allocate_unique` family of function templates provide convenient and safe
19 ways to obtain a `std::unique_ptr` that manages a new object created using an
24 The {cpp}14 standard introduced `std::make_unique` which used operator `new` to
25 create new objects. However, there is no convenient facility in the standard
26 library 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`.
33 `allocate_unique` is defined in `<boost/smart_ptr/allocate_unique.hpp>`.
38 template<class T, class A>
41 template<class T, class A>
42 using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A>>;
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);
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);
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);
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);
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);
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);
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);
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);
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);
91 ## Common Requirements
93 The common requirements that apply to all `allocate_unique` and
94 `allocate_unique_noinit` overloads, unless specified otherwise, are described
97 Requires:: `A` shall be an _allocator_. The copy constructor and destructor
98 of `A` shall not throw exceptions.
100 Effects:: 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
102 arguments, as specified by the concrete overload). The object is initialized
103 from 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
105 thrown, the functions have no effect.
107 Returns:: A `std::unique_ptr` instance that stores and owns the address of the
108 newly constructed object.
110 Postconditions:: `r.get() != 0`, where `r` is the return value.
112 Throws:: An exception thrown from `A::allocate`, or from the initialization of
116 * When an object of an array type is specified to be initialized to a value of
117 the same type `v`, this shall be interpreted to mean that each array element
118 of 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
120 shall be interpreted to mean that each array element of the object is
122 * When a (sub)object of non-array type `U` is specified to be initialized to a
123 value `v`, or constructed from `args\...`, `allocate_unique` shall perform this
124 initialization 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
127 to hold an object of type `U`, and `a2` of type `A2` is a potentially rebound
129 * When a (sub)object of non-array type `U` is specified to be
130 default-initialized, `allocate_unique_noinit` shall perform this initialization
131 via the expression `::new(p) U`, where `p` has type `void*` and points to
132 storage suitable to hold an object of type `U`.
133 * When a (sub)object of non-array type `U` is specified to be
134 value-initialized, `allocate_unique` shall perform this initialization via the
135 expression `std::allocator_traits<A2>::construct(a2, p)`, where `p` points to
136 storage suitable to hold an object of type `U` and `a2` of type `A2` is a
137 potentially 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
140 initialization of an array element throws an exception, the initialized
141 elements should be destroyed in the reverse order of their construction.
146 template<class T, class A, class... Args>
147 std::unique_ptr<T, alloc_deleter<T, A>>
148 allocate_unique(const A& a, Args&&... args);
153 Constraints:: `T` is not an array.
154 Returns:: A `std::unique_ptr` to an object of type `T`, constructed from
157 * `auto p = allocate_unique<int>(a);`
158 * `auto p = allocate_unique<std::vector<int>>(a, 16, 1);`
161 template<class T, class A>
162 std::unique_ptr<T, alloc_deleter<T, A>>
163 allocate_unique(const A& a, type_identity_t<T>&& v);
168 Constraints:: `T` is not an array.
169 Returns:: A `std::unique_ptr` to an object of type `T`, constructed from `v`.
170 Example:: `auto p = allocate_unique<std::vector<int>>(a, {1, 2});`
173 template<class T, class A>
174 std::unique_ptr<T, alloc_deleter<T, A>>
175 allocate_unique(const A& a, std::size_t n);
180 Constraints:: `T` is an array of unknown bounds.
181 Returns:: A `std::unique_ptr` to a sequence of `n` value-initialized objects of
182 type `remove_extent_t<T>`.
184 * `auto p = allocate_unique<double[]>(a, 1024);`
185 * `auto p = allocate_unique<double[][2][2]>(a, 6);`
188 template<class T, class A>
189 std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
190 allocate_unique(const A& a);
195 Constraints:: `T` is an array of known bounds.
196 Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` value-initialized
197 objects of type `remove_extent_t<T>`.
199 * `auto p = allocate_unique<double[1024]>(a);`
200 * `auto p = allocate_unique<double[6][2][2]>(a);`
203 template<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);
210 Constraints:: `T` is an array of unknown bounds.
211 Returns:: A `std::unique_ptr` to a sequence of `n` objects of type
212 `remove_extent_t<T>`, each initialized to `v`.
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});`
219 template<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);
226 Constraints:: `T` is an array of known bounds.
227 Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` objects of type
228 `remove_extent_t<T>`, each initialized to `v`.
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});`
235 template<class T, class A>
236 std::unique_ptr<T, alloc_noinit_deleter<T, A>>
237 allocate_unique_noinit(const A& a);
242 Constraints:: `T` is not an array.
243 Returns:: A `std::unique_ptr` to a default-initialized object of type `T`.
244 Example:: `auto p = allocate_unique_noinit<double>(a);`
247 template<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);
254 Constraints:: `T` is an array of unknown bounds.
255 Returns:: A `std::unique_ptr` to a sequence of `n` default-initialized objects
256 of type `remove_extent_t<T>`.
257 Example:: `auto p = allocate_unique_noinit<double[]>(a, 1024);`
260 template<class T, class A>
261 std::unique_ptr<remove_extent_t<T>, alloc_noinit_deleter<T, A>>
262 allocate_unique_noinit(const A& a);
267 Constraints:: `T` is an array of known bounds.
268 Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>`
269 default-initialized objects of type `remove_extent_t<T>`.
270 Example:: `auto p = allocate_unique_noinit<double[1024]>(a);`
274 Class template `alloc_deleter` is the deleter used by the `allocate_unique`
281 template<class T, class A>
282 class alloc_deleter {
284 using pointer = `unspecified`;
286 explicit alloc_deleter(const A& a) noexcept;
288 void operator()(pointer p);
296 using pointer = `unspecified`;
301 A type that satisfies _NullablePointer_.
304 explicit alloc_deleter(const A& a) noexcept;
309 Effects:: Initializes the stored allocator from `a`.
312 void operator()(pointer p);
317 Effects:: Destroys the objects and deallocates the storage referenced by `p`,
318 using the stored allocator.