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