Implement allocate_unique

This commit is contained in:
Glen Fernandes
2019-08-28 22:59:59 -04:00
parent 00f6b5dcb0
commit 60c26acab8
18 changed files with 2308 additions and 0 deletions

View File

@ -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[]

View File

@ -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);`

View File

@ -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`

View File

@ -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.

View File

@ -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;

View File

@ -0,0 +1,501 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
#define BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
#include <boost/core/alloc_construct.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/core/first_scalar.hpp>
#include <boost/core/noinit_adaptor.hpp>
#include <boost/core/pointer_traits.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/extent.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_bounded_array.hpp>
#include <boost/type_traits/is_unbounded_array.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/type_identity.hpp>
#include <boost/config.hpp>
#include <memory>
#include <utility>
namespace boost {
namespace detail {
template<class T>
struct sp_alloc_size {
BOOST_STATIC_CONSTEXPR std::size_t value = 1;
};
template<class T>
struct sp_alloc_size<T[]> {
BOOST_STATIC_CONSTEXPR std::size_t value = sp_alloc_size<T>::value;
};
template<class T, std::size_t N>
struct sp_alloc_size<T[N]> {
BOOST_STATIC_CONSTEXPR std::size_t value = N * sp_alloc_size<T>::value;
};
template<class T>
struct sp_alloc_result {
typedef T type;
};
template<class T, std::size_t N>
struct sp_alloc_result<T[N]> {
typedef T type[];
};
template<class T>
struct sp_alloc_value {
typedef typename boost::remove_cv<typename
boost::remove_extent<T>::type>::type type;
};
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<class A, class T>
struct sp_alloc_to {
typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
};
#else
template<class A, class T>
struct sp_alloc_to {
typedef typename A::template rebind<T>::other type;
};
#endif
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<class A>
struct sp_alloc_type {
typedef typename std::allocator_traits<A>::pointer type;
};
#else
template<class A>
struct sp_alloc_type {
typedef typename A::pointer type;
};
#endif
template<class T, class P>
class sp_alloc_ptr {
public:
typedef T element_type;
sp_alloc_ptr() BOOST_SP_NOEXCEPT
: p_() { }
sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
: p_(p) { }
#if !defined(BOOST_NO_CXX11_NULLPTR)
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
: p_() { }
#endif
T& operator*() const {
return *p_;
}
T* operator->() const BOOST_SP_NOEXCEPT {
return boost::to_address(p_);
}
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
explicit operator bool() const BOOST_SP_NOEXCEPT {
return !!p_;
}
#endif
bool operator!() const BOOST_SP_NOEXCEPT {
return !p_;
}
P ptr() const BOOST_SP_NOEXCEPT {
return p_;
}
BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
return 1;
}
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
static sp_alloc_ptr pointer_to(T& v) {
return sp_alloc_ptr(1,
std::pointer_traits<P>::pointer_to(const_cast<typename
boost::remove_cv<T>::type&>(v)));
}
#endif
private:
P p_;
};
template<class T, class P>
class sp_alloc_ptr<T[], P> {
public:
typedef T element_type;
sp_alloc_ptr() BOOST_SP_NOEXCEPT
: p_() { }
sp_alloc_ptr(std::size_t n, P p) BOOST_SP_NOEXCEPT
: p_(p)
, n_(n) { }
#if !defined(BOOST_NO_CXX11_NULLPTR)
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
: p_() { }
#endif
T& operator[](std::size_t i) const {
return p_[i];
}
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
explicit operator bool() const BOOST_SP_NOEXCEPT {
return !!p_;
}
#endif
bool operator!() const BOOST_SP_NOEXCEPT {
return !p_;
}
P ptr() const BOOST_SP_NOEXCEPT {
return p_;
}
std::size_t size() const BOOST_SP_NOEXCEPT {
return n_;
}
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
static sp_alloc_ptr pointer_to(T& v) {
return sp_alloc_ptr(n_,
std::pointer_traits<P>::pointer_to(const_cast<typename
boost::remove_cv<T>::type&>(v)));
}
#endif
private:
P p_;
std::size_t n_;
};
template<class T, std::size_t N, class P>
class sp_alloc_ptr<T[N], P> {
public:
typedef T element_type;
sp_alloc_ptr() BOOST_SP_NOEXCEPT
: p_() { }
sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
: p_(p) { }
#if !defined(BOOST_NO_CXX11_NULLPTR)
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
: p_() { }
#endif
T& operator[](std::size_t i) const {
return p_[i];
}
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
explicit operator bool() const BOOST_SP_NOEXCEPT {
return !!p_;
}
#endif
bool operator!() const BOOST_SP_NOEXCEPT {
return !p_;
}
P ptr() const BOOST_SP_NOEXCEPT {
return p_;
}
BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
return N;
}
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
static sp_alloc_ptr pointer_to(T& v) {
return sp_alloc_ptr(N,
std::pointer_traits<P>::pointer_to(const_cast<typename
boost::remove_cv<T>::type&>(v)));
}
#endif
private:
P p_;
};
template<class T, class P>
inline bool
operator==(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
{
return lhs.ptr() == rhs.ptr();
}
template<class T, class P>
inline bool
operator!=(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
{
return !(lhs == rhs);
}
#if !defined(BOOST_NO_CXX11_NULLPTR)
template<class T, class P>
inline bool
operator==(const sp_alloc_ptr<T, P>& lhs,
detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
{
return !lhs.ptr();
}
template<class T, class P>
inline bool
operator==(detail::sp_nullptr_t,
const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
{
return !rhs.ptr();
}
template<class T, class P>
inline bool
operator!=(const sp_alloc_ptr<T, P>& lhs,
detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
{
return !!lhs.ptr();
}
template<class T, class P>
inline bool
operator!=(detail::sp_nullptr_t,
const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
{
return !!rhs.ptr();
}
#endif
template<class A>
inline void
sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t,
boost::false_type)
{
boost::alloc_destroy(a, p);
a.deallocate(p, 1);
}
template<class A>
inline void
sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t n,
boost::true_type)
{
#if defined(BOOST_MSVC) && BOOST_MSVC < 1800
if (!p) {
return;
}
#endif
boost::alloc_destroy_n(a, boost::first_scalar(boost::to_address(p)),
n * sp_alloc_size<typename A::value_type>::value);
a.deallocate(p, n);
}
} /* detail */
template<class T, class A>
class alloc_deleter
: empty_value<typename detail::sp_alloc_to<A,
typename detail::sp_alloc_value<T>::type>::type> {
typedef typename detail::sp_alloc_to<A,
typename detail::sp_alloc_value<T>::type>::type allocator;
typedef empty_value<allocator> base;
public:
typedef detail::sp_alloc_ptr<T,
typename detail::sp_alloc_type<allocator>::type> pointer;
explicit alloc_deleter(const allocator& a) BOOST_SP_NOEXCEPT
: base(empty_init_t(), a) { }
void operator()(pointer p) {
detail::sp_alloc_clear(base::get(), p.ptr(), p.size(), is_array<T>());
}
};
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template<class T, class A>
using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A> >;
#endif
namespace detail {
template<class T, class A>
class sp_alloc_make {
public:
typedef typename sp_alloc_to<A,
typename sp_alloc_value<T>::type>::type allocator;
private:
typedef boost::alloc_deleter<T, A> deleter;
public:
typedef std::unique_ptr<typename sp_alloc_result<T>::type, deleter> type;
sp_alloc_make(const A& a, std::size_t n)
: a_(a)
, n_(n)
, p_(a_.allocate(n)) { }
~sp_alloc_make() {
if (p_) {
a_.deallocate(p_, n_);
}
}
typename allocator::value_type* get() const BOOST_SP_NOEXCEPT {
return boost::to_address(p_);
}
allocator& state() BOOST_SP_NOEXCEPT {
return a_;
}
type release() BOOST_SP_NOEXCEPT {
pointer p = p_;
p_ = pointer();
return type(typename deleter::pointer(n_, p), deleter(a_));
}
private:
typedef typename sp_alloc_type<allocator>::type pointer;
allocator a_;
std::size_t n_;
pointer p_;
};
} /* detail */
template<class T, class A>
inline typename enable_if_<!is_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc)
{
detail::sp_alloc_make<T, A> c(alloc, 1);
boost::alloc_construct(c.state(), c.get());
return c.release();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class A, class... Args>
inline typename enable_if_<!is_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc, Args&&... args)
{
detail::sp_alloc_make<T, A> c(alloc, 1);
boost::alloc_construct(c.state(), c.get(), std::forward<Args>(args)...);
return c.release();
}
#endif
template<class T, class A>
inline typename enable_if_<!is_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc, typename type_identity<T>::type&& value)
{
detail::sp_alloc_make<T, A> c(alloc, 1);
boost::alloc_construct(c.state(), c.get(), std::move(value));
return c.release();
}
template<class T, class A>
inline typename enable_if_<!is_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
allocate_unique_noinit(const A& alloc)
{
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc, std::size_t size)
{
detail::sp_alloc_make<T, A> c(alloc, size);
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
size * detail::sp_alloc_size<T>::value);
return c.release();
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc)
{
detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
detail::sp_alloc_size<T>::value);
return c.release();
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
allocate_unique_noinit(const A& alloc, std::size_t size)
{
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc, size);
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
alloc_deleter<T, noinit_adaptor<A> > > >::type
allocate_unique_noinit(const A& alloc)
{
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc, std::size_t size,
const typename remove_extent<T>::type& value)
{
detail::sp_alloc_make<T, A> c(alloc, size);
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
size * detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
detail::sp_alloc_size<typename remove_extent<T>::type>::value);
return c.release();
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc,
const typename remove_extent<T>::type& value)
{
detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
detail::sp_alloc_size<typename remove_extent<T>::type>::value);
return c.release();
}
} /* boost */
#endif

View File

@ -319,3 +319,15 @@ run get_deleter_test3.cpp : : : <rtti>off <toolset>gcc-4.4.7,<cxxstd>0x:<build>n
run shared_from_test.cpp ;
run weak_from_test.cpp ;
run weak_from_test2.cpp ;
run allocate_unique_args_test.cpp ;
run allocate_unique_array_construct_test.cpp ;
run allocate_unique_array_noinit_test.cpp ;
run allocate_unique_arrays_test.cpp ;
run allocate_unique_array_test.cpp ;
run allocate_unique_array_throws_test.cpp ;
run allocate_unique_array_value_test.cpp ;
run allocate_unique_construct_test.cpp ;
run allocate_unique_noinit_test.cpp ;
run allocate_unique_test.cpp ;
run allocate_unique_throws_test.cpp ;

View File

@ -0,0 +1,111 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 46000) && \
!defined(BOOST_NO_CXX11_SMART_PTR) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
type(int v1, int v2, int v3, int v4, int v5)
: sum_(v1 + v2 + v3 + v4 + v5) {
++instances;
}
~type() {
--instances;
}
int sum() const {
return sum_;
}
private:
int sum_;
type(const type&);
type& operator=(const type&);
};
unsigned type::instances = 0;
int main()
{
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type,
boost::alloc_deleter<type, creator<type> > > result =
boost::allocate_unique<type>(creator<type>(), 1, 2, 3, 4, 5);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(result->sum() == 15);
result.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<const type,
boost::alloc_deleter<const type, creator<> > > result =
boost::allocate_unique<const type>(creator<>(), 1, 2, 3, 4, 5);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 1);
BOOST_TEST(result->sum() == 15);
result.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,166 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 48000) && \
!defined(BOOST_NO_CXX11_SMART_PTR) && \
!defined(BOOST_NO_CXX11_ALLOCATOR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
struct allow { };
template<class T = void>
struct creator {
typedef T value_type;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
template<class U>
void construct(U* ptr) {
::new(static_cast<void*>(ptr)) U(allow());
}
template<class U>
void destroy(U* ptr) {
ptr->~U();
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
explicit type(allow) {
++instances;
}
~type() {
--instances;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned type::instances = 0;
int main()
{
{
std::unique_ptr<type[],
boost::alloc_deleter<type[], creator<type> > > result =
boost::allocate_unique<type[]>(creator<type>(), 3);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[],
boost::alloc_deleter<type[3], creator<type> > > result =
boost::allocate_unique<type[3]>(creator<type>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[][2],
boost::alloc_deleter<type[][2], creator<> > > result =
boost::allocate_unique<type[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[][2],
boost::alloc_deleter<type[2][2], creator<> > > result =
boost::allocate_unique<type[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[],
boost::alloc_deleter<const type[], creator<> > > result =
boost::allocate_unique<const type[]>(creator<>(), 3);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[],
boost::alloc_deleter<const type[3], creator<> > > result =
boost::allocate_unique<const type[3]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[][2],
boost::alloc_deleter<const type[][2], creator<> > > result =
boost::allocate_unique<const type[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[][2],
boost::alloc_deleter<const type[2][2], creator<> > > result =
boost::allocate_unique<const type[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,228 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 48000) && \
!defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
type()
: value_(0.0) {
++instances;
}
~type() {
--instances;
}
void set(long double value) {
value_ = value;
}
long double get() const {
return value_;
}
private:
type(const type&);
type& operator=(const type&);
long double value_;
};
unsigned type::instances = 0;
int main()
{
{
std::unique_ptr<int[],
boost::alloc_deleter<int[],
boost::noinit_adaptor<creator<int> > > > result =
boost::allocate_unique_noinit<int[]>(creator<int>(), 3);
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<int[],
boost::alloc_deleter<int[3],
boost::noinit_adaptor<creator<int> > > > result =
boost::allocate_unique_noinit<int[3]>(creator<int>());
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<int[][2],
boost::alloc_deleter<int[][2],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<int[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<int[][2],
boost::alloc_deleter<int[2][2],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<int[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<const int[],
boost::alloc_deleter<const int[],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const int[]>(creator<>(), 3);
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<const int[],
boost::alloc_deleter<const int[3],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const int[3]>(creator<>());
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<const int[][2],
boost::alloc_deleter<const int[][2],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const int[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<const int[][2],
boost::alloc_deleter<const int[2][2],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const int[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<type[],
boost::alloc_deleter<type[],
boost::noinit_adaptor<creator<type> > > > result =
boost::allocate_unique_noinit<type[]>(creator<type>(), 3);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[],
boost::alloc_deleter<type[3],
boost::noinit_adaptor<creator<type> > > > result =
boost::allocate_unique_noinit<type[3]>(creator<type>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[][2],
boost::alloc_deleter<type[][2],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<type[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[][2],
boost::alloc_deleter<type[2][2],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<type[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[],
boost::alloc_deleter<const type[],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const type[]>(creator<>(), 3);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[],
boost::alloc_deleter<const type[3],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const type[3]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[][2],
boost::alloc_deleter<const type[][2],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const type[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[][2],
boost::alloc_deleter<const type[2][2],
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const type[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,240 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 48000) && \
!defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
type()
: value_(0.0) {
++instances;
}
~type() {
--instances;
}
void set(long double value) {
value_ = value;
}
long double get() const {
return value_;
}
private:
type(const type&);
type& operator=(const type&);
long double value_;
};
unsigned type::instances = 0;
int main()
{
{
std::unique_ptr<int[],
boost::alloc_deleter<int[], creator<int> > > result =
boost::allocate_unique<int[]>(creator<int>(), 3);
BOOST_TEST(result.get() != 0);
BOOST_TEST(result[0] == 0);
BOOST_TEST(result[1] == 0);
BOOST_TEST(result[2] == 0);
}
{
std::unique_ptr<int[],
boost::alloc_deleter<int[3], creator<int> > > result =
boost::allocate_unique<int[3]>(creator<int>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(result[0] == 0);
BOOST_TEST(result[1] == 0);
BOOST_TEST(result[2] == 0);
}
{
std::unique_ptr<int[][2],
boost::alloc_deleter<int[][2], creator<> > > result =
boost::allocate_unique<int[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
BOOST_TEST(result[0][0] == 0);
BOOST_TEST(result[0][1] == 0);
BOOST_TEST(result[1][0] == 0);
BOOST_TEST(result[1][1] == 0);
}
{
std::unique_ptr<int[][2],
boost::alloc_deleter<int[2][2], creator<> > > result =
boost::allocate_unique<int[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(result[0][0] == 0);
BOOST_TEST(result[0][1] == 0);
BOOST_TEST(result[1][0] == 0);
BOOST_TEST(result[1][1] == 0);
}
{
std::unique_ptr<const int[],
boost::alloc_deleter<const int[], creator<> > > result =
boost::allocate_unique<const int[]>(creator<>(), 3);
BOOST_TEST(result.get() != 0);
BOOST_TEST(result[0] == 0);
BOOST_TEST(result[1] == 0);
BOOST_TEST(result[2] == 0);
}
{
std::unique_ptr<const int[],
boost::alloc_deleter<const int[3], creator<> > > result =
boost::allocate_unique<const int[3]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(result[0] == 0);
BOOST_TEST(result[1] == 0);
BOOST_TEST(result[2] == 0);
}
{
std::unique_ptr<const int[][2],
boost::alloc_deleter<const int[][2], creator<> > > result =
boost::allocate_unique<const int[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
BOOST_TEST(result[0][0] == 0);
BOOST_TEST(result[0][1] == 0);
BOOST_TEST(result[1][0] == 0);
BOOST_TEST(result[1][1] == 0);
}
{
std::unique_ptr<const int[][2],
boost::alloc_deleter<const int[2][2], creator<> > > result =
boost::allocate_unique<const int[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(result[0][0] == 0);
BOOST_TEST(result[0][1] == 0);
BOOST_TEST(result[1][0] == 0);
BOOST_TEST(result[1][1] == 0);
}
{
std::unique_ptr<type[],
boost::alloc_deleter<type[], creator<type> > > result =
boost::allocate_unique<type[]>(creator<type>(), 3);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[],
boost::alloc_deleter<type[3], creator<type> > > result =
boost::allocate_unique<type[3]>(creator<type>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[][2],
boost::alloc_deleter<type[][2], creator<> > > result =
boost::allocate_unique<type[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<type[][2],
boost::alloc_deleter<type[2][2], creator<> > > result =
boost::allocate_unique<type[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[],
boost::alloc_deleter<const type[], creator<> > > result =
boost::allocate_unique<const type[]>(creator<>(), 3);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[],
boost::alloc_deleter<const type[3], creator<> > > result =
boost::allocate_unique<const type[3]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 3);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[][2],
boost::alloc_deleter<const type[][2], creator<> > > result =
boost::allocate_unique<const type[][2]>(creator<>(), 2);
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type[][2],
boost::alloc_deleter<const type[2][2], creator<> > > result =
boost::allocate_unique<const type[2][2]>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 4);
result.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,132 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 48000) && \
!defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
type() {
if (instances == 5) {
throw true;
}
++instances;
}
~type() {
--instances;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned type::instances = 0;
int main()
{
try {
boost::allocate_unique<type[]>(creator<type>(), 6);
BOOST_ERROR("allocate_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
try {
boost::allocate_unique<type[][2]>(creator<type>(), 3);
BOOST_ERROR("allocate_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
try {
boost::allocate_unique<type[6]>(creator<>());
BOOST_ERROR("allocate_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
try {
boost::allocate_unique<type[3][2]>(creator<>());
BOOST_ERROR("allocate_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
try {
boost::allocate_unique_noinit<type[]>(creator<>(), 6);
BOOST_ERROR("allocate_unique_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
try {
boost::allocate_unique_noinit<type[][2]>(creator<>(), 3);
BOOST_ERROR("allocate_unique_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
try {
boost::allocate_unique_noinit<type[6]>(creator<>());
BOOST_ERROR("allocate_unique_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
try {
boost::allocate_unique_noinit<type[3][2]>(creator<>());
BOOST_ERROR("allocate_unique_noinit did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,98 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 48000) && \
!defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
int main()
{
{
std::unique_ptr<int[],
boost::alloc_deleter<int[], creator<int> > > result =
boost::allocate_unique<int[]>(creator<int>(), 4, 1);
BOOST_TEST(result[0] == 1);
BOOST_TEST(result[1] == 1);
BOOST_TEST(result[2] == 1);
BOOST_TEST(result[3] == 1);
}
{
std::unique_ptr<int[],
boost::alloc_deleter<int[4], creator<int> > > result =
boost::allocate_unique<int[4]>(creator<int>(), 1);
BOOST_TEST(result[0] == 1);
BOOST_TEST(result[1] == 1);
BOOST_TEST(result[2] == 1);
BOOST_TEST(result[3] == 1);
}
{
std::unique_ptr<const int[],
boost::alloc_deleter<const int[], creator<> > > result =
boost::allocate_unique<const int[]>(creator<>(), 4, 1);
BOOST_TEST(result[0] == 1);
BOOST_TEST(result[1] == 1);
BOOST_TEST(result[2] == 1);
BOOST_TEST(result[3] == 1);
}
{
std::unique_ptr<const int[],
boost::alloc_deleter<const int[4], creator<> > > result =
boost::allocate_unique<const int[4]>(creator<>(), 1);
BOOST_TEST(result[0] == 1);
BOOST_TEST(result[1] == 1);
BOOST_TEST(result[2] == 1);
BOOST_TEST(result[3] == 1);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,99 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 48000) && \
!defined(BOOST_NO_CXX11_SMART_PTR) && \
!defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
int main()
{
{
std::unique_ptr<int[][2],
boost::alloc_deleter<int[][2], creator<int> > > result =
boost::allocate_unique<int[][2]>(creator<int>(), 2, {0, 1});
BOOST_TEST(result[0][0] == 0);
BOOST_TEST(result[0][1] == 1);
BOOST_TEST(result[1][0] == 0);
BOOST_TEST(result[1][1] == 1);
}
{
std::unique_ptr<int[][2],
boost::alloc_deleter<int[2][2], creator<int> > > result =
boost::allocate_unique<int[2][2]>(creator<int>(), {0, 1});
BOOST_TEST(result[0][0] == 0);
BOOST_TEST(result[0][1] == 1);
BOOST_TEST(result[1][0] == 0);
BOOST_TEST(result[1][1] == 1);
}
{
std::unique_ptr<const int[][2],
boost::alloc_deleter<const int[][2], creator<> > > result =
boost::allocate_unique<const int[][2]>(creator<>(), 2, {0, 1});
BOOST_TEST(result[0][0] == 0);
BOOST_TEST(result[0][1] == 1);
BOOST_TEST(result[1][0] == 0);
BOOST_TEST(result[1][1] == 1);
}
{
std::unique_ptr<const int[][2],
boost::alloc_deleter<const int[2][2], creator<> > > result =
boost::allocate_unique<const int[2][2]>(creator<>(), {0, 1});
BOOST_TEST(result[0][0] == 0);
BOOST_TEST(result[0][1] == 1);
BOOST_TEST(result[1][0] == 0);
BOOST_TEST(result[1][1] == 1);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,109 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_SMART_PTR) && !defined(BOOST_NO_CXX11_ALLOCATOR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
struct allow { };
template<class T = void>
struct creator {
typedef T value_type;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
template<class U>
void construct(U* ptr) {
::new(static_cast<void*>(ptr)) U(allow());
}
template<class U>
void destroy(U* ptr) {
ptr->~U();
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
explicit type(allow) {
++instances;
}
~type() {
--instances;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned type::instances = 0;
int main()
{
{
std::unique_ptr<type,
boost::alloc_deleter<type, creator<type> > > result =
boost::allocate_unique<type>(creator<type>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 1);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type,
boost::alloc_deleter<const type, creator<> > > result =
boost::allocate_unique<const type>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 1);
result.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,126 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 46000) && \
!defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
type()
: value_(0.0) {
++instances;
}
~type() {
--instances;
}
void set(long double value) {
value_ = value;
}
long double get() const {
return value_;
}
private:
type(const type&);
type& operator=(const type&);
long double value_;
};
unsigned type::instances = 0;
int main()
{
{
std::unique_ptr<int,
boost::alloc_deleter<int,
boost::noinit_adaptor<creator<int> > > > result =
boost::allocate_unique_noinit<int>(creator<int>());
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<const int,
boost::alloc_deleter<const int,
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const int>(creator<>());
BOOST_TEST(result.get() != 0);
}
{
std::unique_ptr<type,
boost::alloc_deleter<type,
boost::noinit_adaptor<creator<type> > > > result =
boost::allocate_unique_noinit<type>(creator<type>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 1);
result.reset();
BOOST_TEST(type::instances == 0);
}
{
std::unique_ptr<const type,
boost::alloc_deleter<const type,
boost::noinit_adaptor<creator<> > > > result =
boost::allocate_unique_noinit<const type>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 1);
result.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,115 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 46000) && \
!defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
type() {
++instances;
}
~type() {
--instances;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned type::instances = 0;
int main()
{
{
std::unique_ptr<int,
boost::alloc_deleter<int, creator<int> > > result =
boost::allocate_unique<int>(creator<int>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(*result == 0);
}
{
std::unique_ptr<const int,
boost::alloc_deleter<const int, creator<> > > result =
boost::allocate_unique<const int>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(*result == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<type,
boost::alloc_deleter<type, creator<type> > > result =
boost::allocate_unique<type>(creator<type>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 1);
result.reset();
BOOST_TEST(type::instances == 0);
}
BOOST_TEST(type::instances == 0);
{
std::unique_ptr<const type,
boost::alloc_deleter<const type, creator<> > > result =
boost::allocate_unique<const type>(creator<>());
BOOST_TEST(result.get() != 0);
BOOST_TEST(type::instances == 1);
result.reset();
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif

View File

@ -0,0 +1,96 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if (!defined(BOOST_LIBSTDCXX_VERSION) || \
BOOST_LIBSTDCXX_VERSION >= 46000) && \
!defined(BOOST_NO_CXX11_SMART_PTR)
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/allocate_unique.hpp>
template<class T = void>
struct creator {
typedef T value_type;
typedef T* pointer;
template<class U>
struct rebind {
typedef creator<U> other;
};
creator() { }
template<class U>
creator(const creator<U>&) { }
T* allocate(std::size_t size) {
return static_cast<T*>(::operator new(sizeof(T) * size));
}
void deallocate(T* ptr, std::size_t) {
::operator delete(ptr);
}
};
template<class T, class U>
inline bool
operator==(const creator<T>&, const creator<U>&)
{
return true;
}
template<class T, class U>
inline bool
operator!=(const creator<T>&, const creator<U>&)
{
return false;
}
class type {
public:
static unsigned instances;
type() {
if (instances == 0) {
throw true;
}
++instances;
}
~type() {
--instances;
}
private:
type(const type&);
type& operator=(const type&);
};
unsigned type::instances = 0;
int main()
{
try {
boost::allocate_unique<type>(creator<type>());
BOOST_ERROR("allocate_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
try {
boost::allocate_unique<const type>(creator<>());
BOOST_ERROR("allocate_unique did not throw");
} catch (...) {
BOOST_TEST(type::instances == 0);
}
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif