//// Copyright 2019-2021 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// [#allocate_unique] # allocate_unique: Creating unique_ptr :toc: :toc-title: :idprefix: allocate_unique_ ## Description The `allocate_unique` family of function templates provide convenient and safe ways to obtain a `std::unique_ptr` that manages a new object created using an allocator. ## Rationale The {cpp}14 standard introduced `std::make_unique` which used operator `new` to create new objects. However, there is no convenient facility in the standard library to use an allocator for the creation of the objects managed by `std::unique_ptr`. Users writing allocator aware code have often requested an `allocate_unique` factory function. This function is to `std::unique_ptr` what `std::allocate_shared` is to `std::shared_ptr`. ## Synopsis `allocate_unique` is defined in ``. [subs=+quotes] ``` namespace boost { template class alloc_deleter; template using alloc_noinit_deleter = alloc_deleter>; `// T is not an array` template std::unique_ptr> allocate_unique(const A& a, Args&&... args); `// T is not an array` template std::unique_ptr> allocate_unique(const A& a, type_identity_t&& v); `// T is an array of unknown bounds` template std::unique_ptr> allocate_unique(const A& a, std::size_t n); `// T is an array of known bounds` template std::unique_ptr[], alloc_deleter> allocate_unique(const A& a); `// T is an array of unknown bounds` template std::unique_ptr> allocate_unique(const A& a, std::size_t n, const remove_extent_t& v); `// T is an array of known bounds` template std::unique_ptr[], alloc_deleter> allocate_unique(const A& a, const remove_extent_t& v); `// T is not an array` template std::unique_ptr> allocate_unique_noinit(const A& a); `// T is an array of unknown bounds` template std::unique_ptr> allocate_unique_noinit(const A& a, std::size_t n); `// T is an array of known bounds` template std::unique_ptr[], alloc_noinit_deleter> allocate_unique_noinit(const A& a); template allocator_pointer_t>>> get_allocator_pointer(const std::unique_ptr>& p) noexcept; } ``` ## Common Requirements The common requirements that apply to all `allocate_unique` and `allocate_unique_noinit` overloads, unless specified otherwise, are described below. Requires:: `A` shall be an _allocator_. The copy constructor and destructor of `A` shall not throw exceptions. Effects:: Allocates memory for an object of type `T` or `n` objects of `U` (if `T` is an array type of the form `U[]` and `n` is determined by arguments, as specified by the concrete overload). The object is initialized from arguments as specified by the concrete overload. Uses a rebound copy of `a` (for an unspecified `value_type`) to allocate memory. If an exception is thrown, the functions have no effect. Returns:: A `std::unique_ptr` instance that stores and owns the address of the newly constructed object. Postconditions:: `r.get() != 0`, where `r` is the return value. Throws:: An exception thrown from `A::allocate`, or from the initialization of the object. Remarks:: * When an object of an array type is specified to be initialized to a value of the same type `v`, this shall be interpreted to mean that each array element of the object is initialized to the corresponding element from `v`. * When an object of an array type is specified to be value-initialized, this shall be interpreted to mean that each array element of the object is value-initialized. * When a (sub)object of non-array type `U` is specified to be initialized to a value `v`, or constructed from `args\...`, `allocate_unique` shall perform this initialization via the expression `std::allocator_traits::construct(a2, p, expr)` (where `_expr_` is `v` or `std::forward(args)\...)` respectively), `p` points to storage suitable to hold an object of type `U`, and `a2` of type `A2` is a potentially rebound copy of `a`. * When a (sub)object of non-array type `U` is specified to be default-initialized, `allocate_unique_noinit` shall perform this initialization via the expression `::new(p) U`, where `p` has type `void*` and points to storage suitable to hold an object of type `U`. * When a (sub)object of non-array type `U` is specified to be value-initialized, `allocate_unique` shall perform this initialization via the expression `std::allocator_traits::construct(a2, p)`, where `p` points to storage suitable to hold an object of type `U` and `a2` of type `A2` is a potentially rebound copy of `a`. * Array elements are initialized in ascending order of their addresses. * When the lifetime of the object managed by the return value ends, or when the initialization of an array element throws an exception, the initialized elements should be destroyed in the reverse order of their construction. ## Free Functions ``` template std::unique_ptr> allocate_unique(const A& a, Args&&... args); ``` [none] * {blank} + Constraints:: `T` is not an array. Returns:: A `std::unique_ptr` to an object of type `T`, constructed from `args\...`. Examples:: * `auto p = allocate_unique(a);` * `auto p = allocate_unique>(a, 16, 1);` ``` template std::unique_ptr> allocate_unique(const A& a, type_identity_t&& v); ``` [none] * {blank} + Constraints:: `T` is not an array. Returns:: A `std::unique_ptr` to an object of type `T`, constructed from `v`. Example:: `auto p = allocate_unique>(a, {1, 2});` ``` template std::unique_ptr> allocate_unique(const A& a, std::size_t n); ``` [none] * {blank} + Constraints:: `T` is an array of unknown bounds. Returns:: A `std::unique_ptr` to a sequence of `n` value-initialized objects of type `remove_extent_t`. Examples:: * `auto p = allocate_unique(a, 1024);` * `auto p = allocate_unique(a, 6);` ``` template std::unique_ptr[], alloc_deleter> allocate_unique(const A& a); ``` [none] * {blank} + Constraints:: `T` is an array of known bounds. Returns:: A `std::unique_ptr` to a sequence of `extent_v` value-initialized objects of type `remove_extent_t`. Examples:: * `auto p = allocate_unique(a);` * `auto p = allocate_unique(a);` ``` template std::unique_ptr> allocate_unique(const A& a, std::size_t n, const remove_extent_t& v); ``` [none] * {blank} + Constraints:: `T` is an array of unknown bounds. Returns:: A `std::unique_ptr` to a sequence of `n` objects of type `remove_extent_t`, each initialized to `v`. Examples:: * `auto p = allocate_unique(a, 1024, 1.0);` * `auto p = allocate_unique(a, 6, {1.0, 0.0});` * `auto p = allocate_unique[]>(a, 4, {1, 2});` ``` template std::unique_ptr[], alloc_deleter> allocate_unique(const A& a, const remove_extent_t& v); ``` [none] * {blank} + Constraints:: `T` is an array of known bounds. Returns:: A `std::unique_ptr` to a sequence of `extent_v` objects of type `remove_extent_t`, each initialized to `v`. Examples:: * `auto p = allocate_unique(a, 1.0);` * `auto p = allocate_unique(a, {1.0, 0.0});` * `auto p = allocate_unique[4]>(a, {1, 2});` ``` template std::unique_ptr> allocate_unique_noinit(const A& a); ``` [none] * {blank} + Constraints:: `T` is not an array. Returns:: A `std::unique_ptr` to a default-initialized object of type `T`. Example:: `auto p = allocate_unique_noinit(a);` ``` template std::unique_ptr> allocate_unique_noinit(const A& a, std::size_t n); ``` [none] * {blank} + Constraints:: `T` is an array of unknown bounds. Returns:: A `std::unique_ptr` to a sequence of `n` default-initialized objects of type `remove_extent_t`. Example:: `auto p = allocate_unique_noinit(a, 1024);` ``` template std::unique_ptr, alloc_noinit_deleter> allocate_unique_noinit(const A& a); ``` [none] * {blank} + Constraints:: `T` is an array of known bounds. Returns:: A `std::unique_ptr` to a sequence of `extent_v` default-initialized objects of type `remove_extent_t`. Example:: `auto p = allocate_unique_noinit(a);` ``` template allocator_pointer_t>>> get_allocator_pointer(const std::unique_ptr>& p) noexcept; ``` [none] * {blank} + Returns:: The allocator pointer to the allocation. Example:: `auto r = boost::get_allocator_ptr(p);` ## Deleter Class template `alloc_deleter` is the deleter used by the `allocate_unique` functions. ### Synopsis [subs=+quotes] ``` template class alloc_deleter { public: using pointer = `unspecified`; explicit alloc_deleter(const A& a) noexcept; void operator()(pointer p); }; ``` ### Members [subs=+quotes] ``` using pointer = `unspecified`; ``` [none] * {blank} + A type that satisfies _NullablePointer_. ``` explicit alloc_deleter(const A& a) noexcept; ``` [none] * {blank} + Effects:: Initializes the stored allocator from `a`. ``` void operator()(pointer p); ``` [none] * {blank} + Effects:: Destroys the objects and deallocates the storage referenced by `p`, using the stored allocator.