diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 86d4065..04c8f2b 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -12,36 +12,44 @@ #include #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; + typedef typename shared_ptr::element_type T1; + typedef typename detail::array_type::type T2; T1* p1 = 0; - detail::allocate_array_helper a1(allocator, size, &p1); - detail::array_deleter d1; + T2* p2 = 0; + size_t n1 = size * detail::array_size::size; + detail::allocate_array_helper a1(allocator, n1, &p2); + detail::array_deleter d1; shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; - d2 = get_deleter >(s1); - d2->construct(p1, size); + detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct(p2, n1); 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; + typedef typename shared_ptr::element_type T1; + typedef typename detail::array_type::type T2; 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); + T2* p2 = 0; + size_t n1 = size * detail::array_size::size; + detail::allocate_array_helper a1(allocator, n1, &p2); + detail::array_deleter d1; + shared_ptr s1(p2, d1, a1); + detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct(p2, n1, std::forward(args)...); + return shared_ptr(s1, p1) } #endif } diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index de8b304..11f195b 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -10,7 +10,6 @@ #define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #include -#include #include namespace boost { @@ -24,31 +23,34 @@ namespace boost { ~array_deleter() { destroy(); } - void construct(T* memory, std::size_t count) { - for (object = memory; size < count; size++) { - array_helper::create(object[size]); + void construct(void* memory, std::size_t count) { + for (object = static_cast(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++) { - array_helper::create(object[size], args...); + void construct(void* memory, std::size_t count, Args&&... args) { + for (object = static_cast(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++) { - array_helper::create_noinit(object[size]); + void construct_noinit(void* memory, std::size_t count) { + for (object = static_cast(memory); size < count; size++) { + void* p1 = object + size; + ::new(p1) T; } } - void operator()(T*) { + void operator()(const void*) { destroy(); } private: void destroy() { while (size > 0) { - array_helper::destroy(object[--size]); + object[--size].~T(); } } std::size_t size; diff --git a/include/boost/smart_ptr/detail/array_helper.hpp b/include/boost/smart_ptr/detail/array_helper.hpp deleted file mode 100644 index 6d2fe62..0000000 --- a/include/boost/smart_ptr/detail/array_helper.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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_HELPER_HPP -#define BOOST_SMART_PTR_DETAIL_ARRAY_HELPER_HPP - -namespace boost { - namespace detail { - template - struct array_helper { - static void create(T& value) { - void* p1 = &value; - ::new(p1) T(); - } - static void create_noinit(T& value) { - void* p1 = &value; - ::new(p1) T; - } - static void destroy(T& value) { - value.~T(); - } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) - template - static void create(T& value, Args... args) { - void* p1 = &value; - ::new(p1) T(args...); - } -#endif - }; -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - template - struct array_helper { - static void create(T value[N]) { - array_helper::create(value); - array_helper::create(value[N-1]); - } - static void create_noinit(T value[N]) { - array_helper::create_noinit(value); - array_helper::create_noinit(value[N-1]); - } - static void destroy(T value[N]) { - array_helper::destroy(value[N-1]); - array_helper::destroy(value); - } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) - template - static void create(T value[N], Args... args) { - array_helper::create(value, args...); - array_helper::create(value[N-1], args...); - } -#endif - }; - template - struct array_helper { - static void create(T[]) { - } - static void create_noinit(T[]) { - } - static void destroy(T[]) { - } -#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) - template - static void create(T[], Args...) { - } -#endif - }; -#endif - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp new file mode 100644 index 0000000..46b9933 --- /dev/null +++ b/include/boost/smart_ptr/detail/array_traits.hpp @@ -0,0 +1,39 @@ +/* + * 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_TRAITS_HPP +#define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP + +#include + +namespace boost { + namespace detail { + template + struct array_type { + typedef typename boost::remove_cv::type type; + }; + template + struct array_type { + typedef typename array_type::type type; + }; + template + struct array_size { + enum { + size = 1 + }; + }; + template + struct array_size { + enum { + size = N * array_size::size + }; + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index b76cc73..1a9c7f9 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -11,50 +11,62 @@ #include #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; + typedef typename shared_ptr::element_type T1; + typedef typename detail::array_type::type T2; T1* p1 = 0; - detail::make_array_helper a1(size, &p1); - detail::array_deleter d1; + T2* p2 = 0; + size_t n1 = size * detail::array_size::size; + detail::make_array_helper a1(n1, &p2); + detail::array_deleter d1; shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; - d2 = get_deleter >(s1); - d2->construct(p1, size); + detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct(p2, n1); 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; + typedef typename shared_ptr::element_type T1; + typedef typename detail::array_type::type T2; T1* p1 = 0; - detail::make_array_helper a1(size, &p1); - detail::array_deleter d1; + T2* p2 = 0; + size_t n1 = size * detail::array_size::size; + detail::make_array_helper a1(n1, &p2); + 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)...); + detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct(p2, n1, 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; + typedef typename shared_ptr::element_type T1; + typedef typename detail::array_type::type T2; T1* p1 = 0; - detail::make_array_helper a1(size, &p1); - detail::array_deleter d1; + T2* p2 = 0; + size_t n1 = size * detail::array_size::size; + detail::make_array_helper a1(n1, &p2); + detail::array_deleter d1; shared_ptr s1(p1, d1, a1); - detail::array_deleter* d2; - d2 = get_deleter >(s1); - d2->construct_noinit(p1, size); + detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct_noinit(p2, n1); return shared_ptr(s1, p1); } } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index feb38bf..8d22562 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -131,10 +131,12 @@ import testing ; [ compile-fail array_fail_array_access.cpp ] [ run make_shared_array_test.cpp ] + [ run make_shared_arrays_test.cpp ] [ run make_shared_array_throws_test.cpp ] [ run make_shared_array_esft_test.cpp ] [ run make_shared_array_args_test.cpp ] [ run allocate_shared_array_test.cpp ] + [ run allocate_shared_arrays_test.cpp ] [ run allocate_shared_array_throws_test.cpp ] [ run allocate_shared_array_esft_test.cpp ] ;