diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp new file mode 100644 index 0000000..7b32dd5 --- /dev/null +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP +#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP + +#include +#include +#include +#include +#include + +namespace boost { + template + inline typename detail::sp_if_array::type + allocate_shared(const A& allocator, size_t size) { + typedef typename remove_cv::element_type>::type T1; + T1* p1 = 0; + detail::allocate_array_helper a1(allocator, size, &p1); + detail::array_deleter d1; + shared_ptr s1(p1, d1, a1); + detail::array_deleter* d2; + d2 = get_deleter >(s1); + d2->construct(p1, size); + return shared_ptr(s1, p1); + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + template + inline typename detail::sp_if_array::type + allocate_shared(const A& allocator, size_t size, Args&&... args) { + typedef typename remove_cv::element_type>::type T1; + T1* p1 = 0; + detail::allocate_array_helper a1(allocator, size, &p1); + detail::array_deleter d1; + shared_ptr s1(p1, d1, a1); + detail::array_deleter* d2; + d2 = get_deleter >(s1); + d2->construct(p1, size, std::forward(args)...); + return shared_ptr(s1, p1); + } +#endif +} + +#endif diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp new file mode 100644 index 0000000..deddf04 --- /dev/null +++ b/include/boost/smart_ptr/detail/allocate_array_helper.hpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP +#define BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP + +#include +#include + +namespace boost { + namespace detail { + template + class allocate_array_helper { + template + friend class allocate_array_helper; + typedef typename A::rebind ::other A2; + typedef typename A::rebind::other A3; + public: + typedef typename A2::value_type value_type; + typedef typename A2::pointer pointer; + typedef typename A2::const_pointer const_pointer; + typedef typename A2::reference reference; + typedef typename A2::const_reference const_reference; + typedef typename A2::size_type size_type; + typedef typename A2::difference_type difference_type; + template + struct rebind { + typedef allocate_array_helper other; + }; + allocate_array_helper(const A& allocator, std::size_t size, T** data) + : allocator(allocator), + size(sizeof(T) * size), + data(data) { + } + allocate_array_helper(const allocate_array_helper& other) + : allocator(other.allocator), + size(other.size), + data(other.data) { + } + template + allocate_array_helper(const allocate_array_helper& other) + : allocator(other.allocator), + size(other.size), + data(other.data) { + } + pointer address(reference value) const { + return allocator.address(value); + } + const_pointer address(const_reference value) const { + return allocator.address(value); + } + size_type max_size() const { + return allocator.max_size(); + } + pointer allocate(size_type count, const void* value = 0) { + std::size_t a1 = alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + char* p1 = A3(allocator).allocate(n1 + size, value); + char* p2 = p1 + n1; + while (std::size_t(p2) % a1 != 0) { + p2--; + } + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); + } + void deallocate(pointer memory, size_type count) { + std::size_t a1 = alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + char* p1 = reinterpret_cast(memory); + A3(allocator).deallocate(p1, n1 + size); + } + void construct(pointer memory, const Y& value) { + allocator.construct(memory, value); + } + void destroy(pointer memory) { + allocator.destroy(memory); + } + template + bool operator==(const allocate_array_helper& other) const { + return allocator == other.allocator; + } + template + bool operator!=(const allocate_array_helper& other) const { + return !(*this == other); + } + private: + A2 allocator; + std::size_t size; + T** data; + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp new file mode 100644 index 0000000..6f06401 --- /dev/null +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP +#define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP + +#include +#include + +namespace boost { + namespace detail { + template + class array_deleter { + public: + array_deleter() + : size(0) { + } + ~array_deleter() { + destroy(); + } + void construct(T* memory, std::size_t count) { + for (object = memory; size < count; size++) { + void* p1 = object + size; + ::new(p1) T(); + } + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + template + void construct(T* memory, std::size_t count, Args&&... args) { + for (object = memory; size < count; size++) { + void* p1 = object + size; + ::new(p1) T(args...); + } + } +#endif + void construct_noinit(T* memory, std::size_t count) { + for (object = memory; size < count; size++) { + void* p1 = object + size; + ::new(p1) T; + } + } + void operator()(T*) { + destroy(); + } + private: + void destroy() { + while (size > 0) { + object[--size].~T(); + } + } + std::size_t size; + T* object; + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp new file mode 100644 index 0000000..db77aea --- /dev/null +++ b/include/boost/smart_ptr/detail/make_array_helper.hpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP +#define BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP + +#include +#include + +namespace boost { + namespace detail { + template + class make_array_helper { + template + friend class make_array_helper; + public: + typedef typename Y value_type; + typedef typename Y* pointer; + typedef typename const Y* const_pointer; + typedef typename Y& reference; + typedef typename const Y& const_reference; + typedef typename std::size_t size_type; + typedef typename ptrdiff_t difference_type; + template + struct rebind { + typedef make_array_helper other; + }; + make_array_helper(std::size_t size, T** data) + : size(sizeof(T) * size), + data(data) { + } + make_array_helper(const make_array_helper& other) + : size(other.size), + data(other.data) { + } + template + make_array_helper(const make_array_helper& other) + : size(other.size), + data(other.data) { + } + pointer address(reference value) const { + return &value; + } + const_pointer address(const_reference value) const { + return &value; + } + size_type max_size() const { + return static_cast(-1) / sizeof(Y); + } + pointer allocate(size_type count, const void* = 0) { + std::size_t a1 = alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + void* p1 = ::operator new(n1 + size); + char* p2 = static_cast(p1) + n1; + while (std::size_t(p2) % a1 != 0) { + p2--; + } + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); + } + void deallocate(pointer memory, size_type) { + void* p1 = memory; + ::operator delete(p1); + } + void construct(pointer memory, const Y& value) { + void* p1 = memory; + ::new(p1) Y(value); + } + void destroy(pointer memory) { + memory->~Y(); + } + template + bool operator==(const make_array_helper& other) const { + return true; + } + template + bool operator!=(const make_array_helper& other) const { + return !(*this == other); + } + private: + std::size_t size; + T** data; + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/detail/sp_if_array.hpp b/include/boost/smart_ptr/detail/sp_if_array.hpp new file mode 100644 index 0000000..b907294 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_if_array.hpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP +#define BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP + +#include + +namespace boost { + namespace detail { + template + struct sp_if_array { + }; +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + template + struct sp_if_array { + typedef boost::shared_ptr type; + }; +#endif + } +} + +#endif diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp new file mode 100644 index 0000000..1550178 --- /dev/null +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP +#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP + +#include +#include +#include +#include +#include + +namespace boost { + template + inline typename detail::sp_if_array::type + make_shared(std::size_t size) { + typedef typename remove_cv::element_type>::type T1; + T1* p1 = 0; + detail::make_array_helper a1(size, &p1); + detail::array_deleter d1; + shared_ptr s1(p1, d1, a1); + detail::array_deleter* d2; + d2 = get_deleter >(s1); + d2->construct(p1, size); + return shared_ptr(s1, p1); + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + template + inline typename detail::sp_if_array::type + make_shared(std::size_t size, Args&&... args) { + typedef typename remove_cv::element_type>::type T1; + T1* p1 = 0; + detail::make_array_helper a1(size, &p1); + detail::array_deleter d1; + shared_ptr s1(p1, d1, a1); + detail::array_deleter* d2; + d2 = get_deleter >(s1); + d2->construct(p1, size, std::forward(args)...); + return shared_ptr(s1, p1); + } +#endif + template + inline typename detail::sp_if_array::type + make_shared_noinit(std::size_t size) { + typedef typename remove_cv::element_type>::type T1; + T1* p1 = 0; + detail::make_array_helper a1(size, &p1); + detail::array_deleter d1; + shared_ptr s1(p1, d1, a1); + detail::array_deleter* d2; + d2 = get_deleter >(s1); + d2->construct_noinit(p1, size); + return shared_ptr(s1, p1); + } +} + +#endif diff --git a/make_shared_array.html b/make_shared_array.html new file mode 100644 index 0000000..e35350c --- /dev/null +++ b/make_shared_array.html @@ -0,0 +1,100 @@ + + + + make_shared and allocate_shared + + + +

boost.png (6897 bytes)make_shared and allocate_shared + for arrays

+

Introduction
+ Synopsis
+ Free Functions
+ Example
+

Introduction

+

One criticism of Boost shared_array is + the lack of utility similar to make_shared + which ensures only a single allocation for an array. A second criticism + is Boost shared_array does not support custom allocators + and so also lacks an allocate_shared utility.

+

The header files <boost/smart_ptr/make_shared_array.hpp> and + <boost/smart_ptr/allocate_shared_array.hpp> provide new function + templates, make_shared and allocate_shared, + to address this need. make_shared uses the global + operator new to allocate memory, whereas + allocate_shared uses an user-supplied allocator, + allowing finer control.

+

Synopsis

+
namespace boost {
+    template<typename T>
+    shared_ptr<T> make_shared(size_t size);
+
+    template<typename T, typename A>
+    shared_ptr<T> allocate_shared(const A& allocator, size_t size);
+    
+#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS)
+    template<typename T, typename... Args>
+    shared_ptr<T> make_shared(size_t size, Args&&... args);
+    
+    template<typename T, typename A, typename... Args>
+    shared_ptr<T> allocate_shared(const A& allocator, size_t size, Args&&... args);
+#endif
+
+    template<typename T>
+    shared_ptr<T> make_shared_noinit(size_t size);
+}
+

Free Functions

+
template<typename T, typename... Args>
+    shared_ptr<T> make_shared(size_t size, Args&&... args);
+template<typename T, typename A, typename... Args>
+    shared_ptr<T> allocate_shared(const A& allocator, size_t size, Args&&... args);
+
+

Requires: The expression + new(pointer) T(std::forward<Args>(args)...), where + pointer is a void* pointing to storage + suitable to hold an object of type T, shall be + well-formed. A shall be an Allocator, as + described in section 20.1.5 (Allocator requirements) + of the C++ Standard. The copy constructor and destructor of + A shall not throw.

+

Effects: Allocates memory suitable for an array of type + T and size size and constructs an array + of objects in it via the placement new expression + new(pointer) T() or + new(pointer) T(std::forward<Args>(args)...). + allocate_shared uses a copy of + allocator to allocate memory. If an exception is thrown, + has no effect.

+

Returns: A shared_ptr instance that stores and + owns the address of the newly constructed array of type T + and size size.

+

Postconditions: + get() != 0 && use_count() == 1.

+

Throws: bad_alloc, or an exception thrown from + A::allocate or the constructor of T.

+

Notes: This implementation allocates the memory required for + the returned shared_ptr and an array of type + T of size size in a single allocation. This + provides efficiency to equivalent to an intrusive smart array + pointer.

+

The prototypes shown above are used if your compiler supports r-value + references and variadic templates. They perfectly forward the + args parameters to the constructors of + T for each array element.

+

Otherwise, you can use the overloads which take only the array size + (and the allocator in case of allocate_shared) and do not + take any constructor arguments. These overloads invoke the default + constructor of T for each array element.

+
+

Example

+
boost::shared_ptr<int[]> array = boost::make_shared<int[]>(size);
+
+

$Date: 2012-10-30 10:12:25 -0800 (Tue, 30 Oct 2012) $

+

Copyright 2012 Glen Fernandes. 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.

+ + diff --git a/test/allocate_shared_array_esft_test.cpp b/test/allocate_shared_array_esft_test.cpp new file mode 100644 index 0000000..3864b81 --- /dev/null +++ b/test/allocate_shared_array_esft_test.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include + +class type + : public boost::enable_shared_from_this { +public: + static unsigned int instances; + explicit type() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + try { + a1[0].shared_from_this(); + BOOST_ERROR("shared_from_this did not throw"); + } catch (const boost::bad_weak_ptr&) { + BOOST_TEST(type::instances == 3); + } + } + return boost::report_errors(); +} diff --git a/test/allocate_shared_array_test.cpp b/test/allocate_shared_array_test.cpp new file mode 100644 index 0000000..db2cffc --- /dev/null +++ b/test/allocate_shared_array_test.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include +#include + +class type { +public: + static unsigned int instances; + explicit type(int = 0, int = 0) + : member() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); + double member; +}; + +unsigned int type::instances = 0; + +int main() { + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::allocate_shared(std::allocator(), 3, 1, 5); + type* a2 = a1.get(); + BOOST_TEST(type::instances == 3); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + return boost::report_errors(); +} diff --git a/test/allocate_shared_array_throws_test.cpp b/test/allocate_shared_array_throws_test.cpp new file mode 100644 index 0000000..e787000 --- /dev/null +++ b/test/allocate_shared_array_throws_test.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + explicit type() { + if (instances == 5) { + throw true; + } + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + BOOST_TEST(type::instances == 0); + try { + boost::allocate_shared(std::allocator(), 6); + BOOST_ERROR("allocate_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); +} diff --git a/test/make_shared_array_esft_test.cpp b/test/make_shared_array_esft_test.cpp new file mode 100644 index 0000000..3431f23 --- /dev/null +++ b/test/make_shared_array_esft_test.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include + +class type + : public boost::enable_shared_from_this { +public: + static unsigned int instances; + explicit type() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3); + try { + a1[0].shared_from_this(); + BOOST_ERROR("shared_from_this did not throw"); + } catch (const boost::bad_weak_ptr&) { + BOOST_TEST(type::instances == 3); + } + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + try { + a1[0].shared_from_this(); + BOOST_ERROR("shared_from_this did not throw"); + } catch (const boost::bad_weak_ptr&) { + BOOST_TEST(type::instances == 3); + } + } + return boost::report_errors(); +} diff --git a/test/make_shared_array_test.cpp b/test/make_shared_array_test.cpp new file mode 100644 index 0000000..6fe2c24 --- /dev/null +++ b/test/make_shared_array_test.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include +#include +#include + +class type { +public: + static unsigned int instances; + explicit type(int = 0, int = 0) + : member() { + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); + double member; +}; + +unsigned int type::instances = 0; + +int main() { + { + boost::shared_ptr a1 = boost::make_shared(3); + int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + { + boost::shared_ptr a1 = boost::make_shared(3); + const int* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(a1[0] == 0); + BOOST_TEST(a1[1] == 0); + BOOST_TEST(a1[2] == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3); + type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3); + const type* a2 = a1.get(); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared(3, 1, 5); + type* a2 = a1.get(); + BOOST_TEST(type::instances == 3); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + a1.reset(); + BOOST_TEST(type::instances == 0); + } +#endif + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + int* a2 = a1.get(); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + const int* a2 = a1.get(); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + type* a2 = a1.get(); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + boost::weak_ptr w1 = a1; + a1.reset(); + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + { + boost::shared_ptr a1 = boost::make_shared_noinit(3); + const type* a2 = a1.get(); + BOOST_TEST(a2 != 0); + BOOST_TEST(size_t(a2) % boost::alignment_of::value == 0); + BOOST_TEST(type::instances == 3); + } + return boost::report_errors(); +} diff --git a/test/make_shared_array_throws_test.cpp b/test/make_shared_array_throws_test.cpp new file mode 100644 index 0000000..2bac909 --- /dev/null +++ b/test/make_shared_array_throws_test.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#include + +class type { +public: + static unsigned int instances; + explicit type() { + if (instances == 5) { + throw true; + } + instances++; + } + ~type() { + instances--; + } +private: + type(const type&); + type& operator=(const type&); +}; + +unsigned int type::instances = 0; + +int main() { + BOOST_TEST(type::instances == 0); + try { + boost::make_shared(6); + BOOST_ERROR("make_shared did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + BOOST_TEST(type::instances == 0); + try { + boost::shared_ptr a1 = boost::make_shared_noinit(6); + BOOST_ERROR("make_shared_noinit did not throw"); + } catch (...) { + BOOST_TEST(type::instances == 0); + } + return boost::report_errors(); +}