forked from boostorg/smart_ptr
Implement allocate_unique
This commit is contained in:
1 parent
00f6b5dcb0
commit
60c26acab8
18 files changed
+2308
No files matched your search
@@ -37,6 +37,8 @@ include::smart_ptr/enable_shared_from.adoc[]
|
||||
|
||||
include::smart_ptr/make_unique.adoc[]
|
||||
|
||||
include::smart_ptr/allocate_unique.adoc[]
|
||||
|
||||
include::smart_ptr/intrusive_ptr.adoc[]
|
||||
|
||||
include::smart_ptr/intrusive_ref_counter.adoc[]
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
////
|
||||
Copyright 2019 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 `<boost/smart_ptr/allocate_unique.hpp>`.
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
namespace boost {
|
||||
`// T is not an array`
|
||||
template<class T, class A, class... Args>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, Args&&... args);
|
||||
|
||||
`// T is not an array`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, type_identity_t<T>&& v);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, std::size_t n);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, std::size_t n, const type_identity_t<T>& v);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, const type_identity_t<T>& v);
|
||||
|
||||
`// T is not an array`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A>>>
|
||||
allocate_unique_noinit(const A& a);
|
||||
|
||||
`// T is an array of unknown bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A>>>
|
||||
allocate_unique(const A& a, std::size_t n);
|
||||
|
||||
`// T is an array of known bounds`
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, noinit_adaptor<A>>>
|
||||
allocate_unique_noinit(const A& a);
|
||||
}
|
||||
```
|
||||
|
||||
## 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<A2>::construct(a2, p, expr)` (where `_expr_` is `v` or
|
||||
`std::forward<Args>(args)\...)` respectively), `p` points to storage suitable
|
||||
to hold an object of type `U`, and `a2` of type `A2` is a rebound copy `a` such
|
||||
that its `value_type` is `U`.
|
||||
* 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<A2>::construct(a2, p)`, where `p` points to
|
||||
storage suitable to hold an object of type `U` and `a2` of type `A2` is a
|
||||
rebound copy of `a` such that its value_type is `U`.
|
||||
* 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<class T, class A, class... Args>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
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<int>(a);`
|
||||
* `auto p = allocate_unique<std::vector<int>>(a, 16, 1);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, type_identity_t<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<std::vector<int>>(a, {1, 2});`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
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<T>`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<double[]>(a, 1024);`
|
||||
* `auto p = allocate_unique<double[][2][2]>(a, 6);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
||||
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<T>` value-initialized
|
||||
objects of type `remove_extent_t<T>`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<double[1024]>(a);`
|
||||
* `auto p = allocate_unique<double[6][2][2]>(a);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, std::size_t n, const type_identity_t<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<T>`, each initialized to `v`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<double[]>(a, 1024, 1.0);`
|
||||
* `auto p = allocate_unique<double[][2]>(a, 6, {1.0, 0.0});`
|
||||
* `auto p = allocate_unique<std::vector<int>[]>(a, 4, {1, 2});`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
|
||||
allocate_unique(const A& a, const type_identity_t<T>& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Constraints:: `T` is an array of known bounds.
|
||||
Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` objects of type
|
||||
`remove_extent_t<T>`, each initialized to `v`.
|
||||
Examples::
|
||||
* `auto p = allocate_unique<double[1024]>(a, 1.0);`
|
||||
* `auto p = allocate_unique<double[6][2]>(a, {1.0, 0.0});`
|
||||
* `auto p = allocate_unique<std::vector<int>[4]>(a, {1, 2});`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A>>>
|
||||
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<double>(a);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A>>>
|
||||
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` default-initialized objects
|
||||
of type `remove_extent_t<T>`.
|
||||
Example:: `auto p = allocate_unique_noinit<double[]>(a, 1024);`
|
||||
|
||||
```
|
||||
template<class T, class A>
|
||||
std::unique_ptr<remove_extent_t<T>, alloc_deleter<T, noinit_adaptor<A>>>
|
||||
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<T>`
|
||||
default-initialized objects of type `remove_extent_t<T>`.
|
||||
Example:: `auto p = allocate_unique_noinit<double[1024]>(a);`
|
||||
@@ -13,6 +13,10 @@ http://www.boost.org/LICENSE_1_0.txt
|
||||
:toc-title:
|
||||
:idprefix: changelog_
|
||||
|
||||
## Changes in 1.72.0
|
||||
|
||||
* Added `allocate_unique`
|
||||
|
||||
## Changes in 1.71.0
|
||||
|
||||
* Added aliasing constructors to `weak_ptr`
|
||||
|
||||
@@ -111,3 +111,7 @@ Glen Fernandes rewrote `allocate_shared` and `make_shared` for arrays for a more
|
||||
Peter Dimov and Glen Fernandes rewrote the documentation in Asciidoc format.
|
||||
|
||||
Peter Dimov added `atomic_shared_ptr` and `local_shared_ptr`.
|
||||
|
||||
## August 2019
|
||||
|
||||
Glen Fernandes implemented `allocate_unique` for scalars and arrays.
|
||||
@@ -41,6 +41,7 @@ In addition, the library contains the following supporting utility functions and
|
||||
|
||||
* `<<make_shared,make_shared>>`, a factory function for creating objects that returns a `shared_ptr`;
|
||||
* `<<make_unique,make_unique>>`, a factory function returning `std::unique_ptr`;
|
||||
* `<<allocate_unique,allocate_unique>>`, a factory function for creating objects using an allocator that returns a `std::unique_ptr`;
|
||||
* `<<enable_shared_from_this,enable_shared_from_this>>`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`;
|
||||
* `<<pointer_to_other,pointer_to_other>>`, a helper trait for converting one smart pointer type to another;
|
||||
* `<<pointer_cast,static_pointer_cast>>` and companions, generic smart pointer casts;
|
||||
|
||||
Reference in new issue
Block a user