From 60c26acab8b3f593fbf86bf9fd18a57a2ee469b9 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 28 Aug 2019 22:59:59 -0400 Subject: [PATCH] Implement allocate_unique --- doc/smart_ptr.adoc | 2 + doc/smart_ptr/allocate_unique.adoc | 264 +++++++++ doc/smart_ptr/changelog.adoc | 4 + doc/smart_ptr/history.adoc | 4 + doc/smart_ptr/introduction.adoc | 1 + include/boost/smart_ptr/allocate_unique.hpp | 501 ++++++++++++++++++ test/Jamfile | 12 + test/allocate_unique_args_test.cpp | 111 ++++ test/allocate_unique_array_construct_test.cpp | 166 ++++++ test/allocate_unique_array_noinit_test.cpp | 228 ++++++++ test/allocate_unique_array_test.cpp | 240 +++++++++ test/allocate_unique_array_throws_test.cpp | 132 +++++ test/allocate_unique_array_value_test.cpp | 98 ++++ test/allocate_unique_arrays_test.cpp | 99 ++++ test/allocate_unique_construct_test.cpp | 109 ++++ test/allocate_unique_noinit_test.cpp | 126 +++++ test/allocate_unique_test.cpp | 115 ++++ test/allocate_unique_throws_test.cpp | 96 ++++ 18 files changed, 2308 insertions(+) create mode 100644 doc/smart_ptr/allocate_unique.adoc create mode 100644 include/boost/smart_ptr/allocate_unique.hpp create mode 100644 test/allocate_unique_args_test.cpp create mode 100644 test/allocate_unique_array_construct_test.cpp create mode 100644 test/allocate_unique_array_noinit_test.cpp create mode 100644 test/allocate_unique_array_test.cpp create mode 100644 test/allocate_unique_array_throws_test.cpp create mode 100644 test/allocate_unique_array_value_test.cpp create mode 100644 test/allocate_unique_arrays_test.cpp create mode 100644 test/allocate_unique_construct_test.cpp create mode 100644 test/allocate_unique_noinit_test.cpp create mode 100644 test/allocate_unique_test.cpp create mode 100644 test/allocate_unique_throws_test.cpp diff --git a/doc/smart_ptr.adoc b/doc/smart_ptr.adoc index 7b854da..69051c7 100644 --- a/doc/smart_ptr.adoc +++ b/doc/smart_ptr.adoc @@ -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[] diff --git a/doc/smart_ptr/allocate_unique.adoc b/doc/smart_ptr/allocate_unique.adoc new file mode 100644 index 0000000..f7f85bc --- /dev/null +++ b/doc/smart_ptr/allocate_unique.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 ``. + +[subs=+quotes] +``` +namespace boost { + `// 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 type_identity_t& v); + + `// T is an array of known bounds` + template + std::unique_ptr[], alloc_deleter> + allocate_unique(const A& a, const type_identity_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(const A& a, std::size_t n); + + `// T is an array of known bounds` + template + std::unique_ptr[], alloc_deleter>> + 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::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 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::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 + 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 type_identity_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 type_identity_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(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_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);` diff --git a/doc/smart_ptr/changelog.adoc b/doc/smart_ptr/changelog.adoc index 43b7b57..bd24e01 100644 --- a/doc/smart_ptr/changelog.adoc +++ b/doc/smart_ptr/changelog.adoc @@ -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` diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc index 914928d..71205ff 100644 --- a/doc/smart_ptr/history.adoc +++ b/doc/smart_ptr/history.adoc @@ -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. diff --git a/doc/smart_ptr/introduction.adoc b/doc/smart_ptr/introduction.adoc index babddf7..1d0a837 100644 --- a/doc/smart_ptr/introduction.adoc +++ b/doc/smart_ptr/introduction.adoc @@ -41,6 +41,7 @@ In addition, the library contains the following supporting utility functions and * `<>`, a factory function for creating objects that returns a `shared_ptr`; * `<>`, a factory function returning `std::unique_ptr`; +* `<>`, a factory function for creating objects using an allocator that returns a `std::unique_ptr`; * `<>`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`; * `<>`, a helper trait for converting one smart pointer type to another; * `<>` and companions, generic smart pointer casts; diff --git a/include/boost/smart_ptr/allocate_unique.hpp b/include/boost/smart_ptr/allocate_unique.hpp new file mode 100644 index 0000000..c413715 --- /dev/null +++ b/include/boost/smart_ptr/allocate_unique.hpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace detail { + +template +struct sp_alloc_size { + BOOST_STATIC_CONSTEXPR std::size_t value = 1; +}; + +template +struct sp_alloc_size { + BOOST_STATIC_CONSTEXPR std::size_t value = sp_alloc_size::value; +}; + +template +struct sp_alloc_size { + BOOST_STATIC_CONSTEXPR std::size_t value = N * sp_alloc_size::value; +}; + +template +struct sp_alloc_result { + typedef T type; +}; + +template +struct sp_alloc_result { + typedef T type[]; +}; + +template +struct sp_alloc_value { + typedef typename boost::remove_cv::type>::type type; +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct sp_alloc_to { + typedef typename std::allocator_traits::template rebind_alloc type; +}; +#else +template +struct sp_alloc_to { + typedef typename A::template rebind::other type; +}; +#endif + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct sp_alloc_type { + typedef typename std::allocator_traits::pointer type; +}; +#else +template +struct sp_alloc_type { + typedef typename A::pointer type; +}; +#endif + +template +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

::pointer_to(const_cast::type&>(v))); + } +#endif + +private: + P p_; +}; + +template +class sp_alloc_ptr { +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

::pointer_to(const_cast::type&>(v))); + } +#endif + +private: + P p_; + std::size_t n_; +}; + +template +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[](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

::pointer_to(const_cast::type&>(v))); + } +#endif + +private: + P p_; +}; + +template +inline bool +operator==(const sp_alloc_ptr& lhs, const sp_alloc_ptr& rhs) +{ + return lhs.ptr() == rhs.ptr(); +} + +template +inline bool +operator!=(const sp_alloc_ptr& lhs, const sp_alloc_ptr& rhs) +{ + return !(lhs == rhs); +} + +#if !defined(BOOST_NO_CXX11_NULLPTR) +template +inline bool +operator==(const sp_alloc_ptr& lhs, + detail::sp_nullptr_t) BOOST_SP_NOEXCEPT +{ + return !lhs.ptr(); +} + +template +inline bool +operator==(detail::sp_nullptr_t, + const sp_alloc_ptr& rhs) BOOST_SP_NOEXCEPT +{ + return !rhs.ptr(); +} + +template +inline bool +operator!=(const sp_alloc_ptr& lhs, + detail::sp_nullptr_t) BOOST_SP_NOEXCEPT +{ + return !!lhs.ptr(); +} + +template +inline bool +operator!=(detail::sp_nullptr_t, + const sp_alloc_ptr& rhs) BOOST_SP_NOEXCEPT +{ + return !!rhs.ptr(); +} +#endif + +template +inline void +sp_alloc_clear(A& a, typename sp_alloc_type::type p, std::size_t, + boost::false_type) +{ + boost::alloc_destroy(a, p); + a.deallocate(p, 1); +} + +template +inline void +sp_alloc_clear(A& a, typename sp_alloc_type::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::value); + a.deallocate(p, n); +} + +} /* detail */ + +template +class alloc_deleter + : empty_value::type>::type> { + typedef typename detail::sp_alloc_to::type>::type allocator; + typedef empty_value base; + +public: + typedef detail::sp_alloc_ptr::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()); + } +}; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +template +using alloc_noinit_deleter = alloc_deleter >; +#endif + +namespace detail { + +template +class sp_alloc_make { +public: + typedef typename sp_alloc_to::type>::type allocator; + +private: + typedef boost::alloc_deleter deleter; + +public: + typedef std::unique_ptr::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::type pointer; + + allocator a_; + std::size_t n_; + pointer p_; +}; + +} /* detail */ + +template +inline typename enable_if_::value, + std::unique_ptr > >::type +allocate_unique(const A& alloc) +{ + detail::sp_alloc_make c(alloc, 1); + boost::alloc_construct(c.state(), c.get()); + return c.release(); +} + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +template +inline typename enable_if_::value, + std::unique_ptr > >::type +allocate_unique(const A& alloc, Args&&... args) +{ + detail::sp_alloc_make c(alloc, 1); + boost::alloc_construct(c.state(), c.get(), std::forward(args)...); + return c.release(); +} +#endif + +template +inline typename enable_if_::value, + std::unique_ptr > >::type +allocate_unique(const A& alloc, typename type_identity::type&& value) +{ + detail::sp_alloc_make c(alloc, 1); + boost::alloc_construct(c.state(), c.get(), std::move(value)); + return c.release(); +} + +template +inline typename enable_if_::value, + std::unique_ptr > > >::type +allocate_unique_noinit(const A& alloc) +{ + return boost::allocate_unique >(alloc); +} + +template +inline typename enable_if_::value, + std::unique_ptr > >::type +allocate_unique(const A& alloc, std::size_t size) +{ + detail::sp_alloc_make c(alloc, size); + boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()), + size * detail::sp_alloc_size::value); + return c.release(); +} + +template +inline typename enable_if_::value, + std::unique_ptr::type, + alloc_deleter > >::type +allocate_unique(const A& alloc) +{ + detail::sp_alloc_make c(alloc, extent::value); + boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()), + detail::sp_alloc_size::value); + return c.release(); +} + +template +inline typename enable_if_::value, + std::unique_ptr > > >::type +allocate_unique_noinit(const A& alloc, std::size_t size) +{ + return boost::allocate_unique >(alloc, size); +} + +template +inline typename enable_if_::value, + std::unique_ptr::type, + alloc_deleter > > >::type +allocate_unique_noinit(const A& alloc) +{ + return boost::allocate_unique >(alloc); +} + +template +inline typename enable_if_::value, + std::unique_ptr > >::type +allocate_unique(const A& alloc, std::size_t size, + const typename remove_extent::type& value) +{ + detail::sp_alloc_make c(alloc, size); + boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()), + size * detail::sp_alloc_size::value, boost::first_scalar(&value), + detail::sp_alloc_size::type>::value); + return c.release(); +} + +template +inline typename enable_if_::value, + std::unique_ptr::type, + alloc_deleter > >::type +allocate_unique(const A& alloc, + const typename remove_extent::type& value) +{ + detail::sp_alloc_make c(alloc, extent::value); + boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()), + detail::sp_alloc_size::value, boost::first_scalar(&value), + detail::sp_alloc_size::type>::value); + return c.release(); +} + +} /* boost */ + +#endif diff --git a/test/Jamfile b/test/Jamfile index 02a8a2e..61b375e 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -319,3 +319,15 @@ run get_deleter_test3.cpp : : : off gcc-4.4.7,0x: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 ; diff --git a/test/allocate_unique_args_test.cpp b/test/allocate_unique_args_test.cpp new file mode 100644 index 0000000..e2f19d0 --- /dev/null +++ b/test/allocate_unique_args_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 46000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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 > > result = + boost::allocate_unique(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); + } + BOOST_TEST(type::instances == 0); + { + std::unique_ptr > > result = + boost::allocate_unique(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 diff --git a/test/allocate_unique_array_construct_test.cpp b/test/allocate_unique_array_construct_test.cpp new file mode 100644 index 0000000..6c9a4aa --- /dev/null +++ b/test/allocate_unique_array_construct_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 48000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) && \ + !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#include + +struct allow { }; + +template +struct creator { + typedef T value_type; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } + + template + void construct(U* ptr) { + ::new(static_cast(ptr)) U(allow()); + } + + template + void destroy(U* ptr) { + ptr->~U(); + } + +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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 > > result = + boost::allocate_unique(creator(), 3); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(), 2); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(), 3); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(), 2); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(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 diff --git a/test/allocate_unique_array_noinit_test.cpp b/test/allocate_unique_array_noinit_test.cpp new file mode 100644 index 0000000..118af3e --- /dev/null +++ b/test/allocate_unique_array_noinit_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 48000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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 > > > result = + boost::allocate_unique_noinit(creator(), 3); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator()); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(), 2); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>()); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(), 3); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>()); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(), 2); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>()); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator(), 3); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(), 2); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(), 3); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>(), 2); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(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 diff --git a/test/allocate_unique_array_test.cpp b/test/allocate_unique_array_test.cpp new file mode 100644 index 0000000..e61e614 --- /dev/null +++ b/test/allocate_unique_array_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 48000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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 > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(creator()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(result[0] == 0); + BOOST_TEST(result[1] == 0); + BOOST_TEST(result[2] == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(creator<>()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(result[0] == 0); + BOOST_TEST(result[1] == 0); + BOOST_TEST(result[2] == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(creator(), 3); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(), 2); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(), 3); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 3); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>(), 2); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 4); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(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 diff --git a/test/allocate_unique_array_throws_test.cpp b/test/allocate_unique_array_throws_test.cpp new file mode 100644 index 0000000..3bdcae1 --- /dev/null +++ b/test/allocate_unique_array_throws_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 48000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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(creator(), 6); + BOOST_ERROR("allocate_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + try { + boost::allocate_unique(creator(), 3); + BOOST_ERROR("allocate_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + try { + boost::allocate_unique(creator<>()); + BOOST_ERROR("allocate_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + try { + boost::allocate_unique(creator<>()); + BOOST_ERROR("allocate_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + try { + boost::allocate_unique_noinit(creator<>(), 6); + BOOST_ERROR("allocate_unique_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + try { + boost::allocate_unique_noinit(creator<>(), 3); + BOOST_ERROR("allocate_unique_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + try { + boost::allocate_unique_noinit(creator<>()); + BOOST_ERROR("allocate_unique_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + try { + boost::allocate_unique_noinit(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 diff --git a/test/allocate_unique_array_value_test.cpp b/test/allocate_unique_array_value_test.cpp new file mode 100644 index 0000000..9bc714b --- /dev/null +++ b/test/allocate_unique_array_value_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 48000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + return false; +} + +int main() +{ + { + std::unique_ptr > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(creator(), 1); + BOOST_TEST(result[0] == 1); + BOOST_TEST(result[1] == 1); + BOOST_TEST(result[2] == 1); + BOOST_TEST(result[3] == 1); + } + { + std::unique_ptr > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(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 diff --git a/test/allocate_unique_arrays_test.cpp b/test/allocate_unique_arrays_test.cpp new file mode 100644 index 0000000..fc2fe33 --- /dev/null +++ b/test/allocate_unique_arrays_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 48000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) && \ + !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + return false; +} + +int main() +{ + { + std::unique_ptr > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(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); + } + { + std::unique_ptr > > result = + boost::allocate_unique(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 > > result = + boost::allocate_unique(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 diff --git a/test/allocate_unique_construct_test.cpp b/test/allocate_unique_construct_test.cpp new file mode 100644 index 0000000..f5b0d45 --- /dev/null +++ b/test/allocate_unique_construct_test.cpp @@ -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 +#if !defined(BOOST_NO_CXX11_SMART_PTR) && !defined(BOOST_NO_CXX11_ALLOCATOR) +#include +#include + +struct allow { }; + +template +struct creator { + typedef T value_type; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } + + template + void construct(U* ptr) { + ::new(static_cast(ptr)) U(allow()); + } + + template + void destroy(U* ptr) { + ptr->~U(); + } + +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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 > > result = + boost::allocate_unique(creator()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 1); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(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 diff --git a/test/allocate_unique_noinit_test.cpp b/test/allocate_unique_noinit_test.cpp new file mode 100644 index 0000000..3dc8a35 --- /dev/null +++ b/test/allocate_unique_noinit_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 46000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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 > > > result = + boost::allocate_unique_noinit(creator()); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator<>()); + BOOST_TEST(result.get() != 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(creator()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(type::instances == 1); + result.reset(); + BOOST_TEST(type::instances == 0); + } + { + std::unique_ptr > > > result = + boost::allocate_unique_noinit(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 diff --git a/test/allocate_unique_test.cpp b/test/allocate_unique_test.cpp new file mode 100644 index 0000000..a919f77 --- /dev/null +++ b/test/allocate_unique_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 46000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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 > > result = + boost::allocate_unique(creator()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(*result == 0); + } + { + std::unique_ptr > > result = + boost::allocate_unique(creator<>()); + BOOST_TEST(result.get() != 0); + BOOST_TEST(*result == 0); + } + BOOST_TEST(type::instances == 0); + { + std::unique_ptr > > result = + boost::allocate_unique(creator()); + 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 > > result = + boost::allocate_unique(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 diff --git a/test/allocate_unique_throws_test.cpp b/test/allocate_unique_throws_test.cpp new file mode 100644 index 0000000..4b948b3 --- /dev/null +++ b/test/allocate_unique_throws_test.cpp @@ -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 +#if (!defined(BOOST_LIBSTDCXX_VERSION) || \ + BOOST_LIBSTDCXX_VERSION >= 46000) && \ + !defined(BOOST_NO_CXX11_SMART_PTR) +#include +#include + +template +struct creator { + typedef T value_type; + typedef T* pointer; + + template + struct rebind { + typedef creator other; + }; + + creator() { } + + template + creator(const creator&) { } + + T* allocate(std::size_t size) { + return static_cast(::operator new(sizeof(T) * size)); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + } +}; + +template +inline bool +operator==(const creator&, const creator&) +{ + return true; +} + +template +inline bool +operator!=(const creator&, const creator&) +{ + 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(creator()); + BOOST_ERROR("allocate_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + try { + boost::allocate_unique(creator<>()); + BOOST_ERROR("allocate_unique did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif