diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index a98d97e..dc24ca2 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include @@ -142,7 +141,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, p3, M); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -166,7 +165,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, p3, M); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } #if defined(BOOST_HAS_RVALUE_REFS) diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 40e9d57..8ef0d11 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -9,8 +9,8 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP -#include -#include +#include +#include namespace boost { namespace detail { @@ -24,97 +24,47 @@ namespace boost { object(0) { } ~array_deleter() { - destroy(size); + if (object) { + array_destroy(object, size); + } } void construct(T* memory) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, size); + object = memory; } #if defined(BOOST_HAS_RVALUE_REFS) void construct(T* memory, T&& value) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(value); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, size, sp_forward(value)); + object = memory; } #if defined(BOOST_HAS_VARIADIC_TMPL) template void construct(T* memory, Args&&... args) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(args...); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, size, sp_forward(args)...); + object = memory; } #endif #endif void construct_list(T* memory, const T* list) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i]); - } - } catch (...) { - destroy(i); - throw; - } + array_construct_list(memory, size, list); + object = memory; } - void construct_list(T* memory, const T* list, std::size_t n) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % n]); - } - } catch (...) { - destroy(i); - throw; - } + template + void construct_list(T* memory, const T* list) { + array_construct_list(memory, size, list); + object = memory; } void construct_noinit(T* memory) { - std::size_t i = 0; - try { - for (object = memory; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T; - } - } catch (...) { - destroy(i); - throw; - } + array_construct_noinit(memory, size); + object = memory; } void operator()(const void*) { - destroy(size); - } - private: - void destroy(std::size_t n) { if (object) { - for (std::size_t i = n; i > 0; ) { - object[--i].~T(); - } + array_destroy(object, size); object = 0; } } + private: std::size_t size; T* object; }; @@ -125,97 +75,47 @@ namespace boost { : object(0) { } ~array_deleter() { - destroy(N); + if (object) { + array_destroy(object, N); + } } void construct(T* memory) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, N); + object = memory; } #if defined(BOOST_HAS_RVALUE_REFS) void construct(T* memory, T&& value) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(value); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, N, sp_forward(value)); + object = memory; } #if defined(BOOST_HAS_VARIADIC_TMPL) template void construct(T* memory, Args&&... args) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(args...); - } - } catch (...) { - destroy(i); - throw; - } + array_construct(memory, N, sp_forward(args)...); + object = memory; } #endif #endif void construct_list(T* memory, const T* list) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i]); - } - } catch (...) { - destroy(i); - throw; - } + array_construct_list(memory, N, list); + object = memory; } - void construct_list(T* memory, const T* list, std::size_t n) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % n]); - } - } catch (...) { - destroy(i); - throw; - } + template + void construct_list(T* memory, const T* list) { + array_construct_list(memory, N, list); + object = memory; } void construct_noinit(T* memory) { - std::size_t i = 0; - try { - for (object = memory; i < N; i++) { - void* p1 = memory + i; - ::new(p1) T; - } - } catch (...) { - destroy(i); - throw; - } + array_construct_noinit(memory, N); + object = memory; } void operator()(const void*) { - destroy(N); - } - private: - void destroy(std::size_t n) { if (object) { - for (std::size_t i = n; i > 0; ) { - object[--i].~T(); - } + array_destroy(object, N); object = 0; } } + private: T* object; }; } diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp new file mode 100644 index 0000000..b584599 --- /dev/null +++ b/include/boost/smart_ptr/detail/array_utility.hpp @@ -0,0 +1,136 @@ +/* + * 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_UTILITY_HPP +#define BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP + +#include +#include +#include + +namespace boost { + namespace detail { + template + inline void array_destroy(T*, std::size_t, boost::true_type) { + } + template + inline void array_destroy(T* memory, std::size_t size, boost::false_type) { + for (std::size_t i = size; i > 0; ) { + memory[--i].~T(); + } + } + template + inline void array_destroy(T* memory, std::size_t size) { + boost::has_trivial_destructor type; + array_destroy(memory, size, type); + } + template + inline void array_construct(T* memory, std::size_t size, boost::true_type) { + for (std::size_t i = 0; i < size; i++) { + memory[i] = T(); + } + } + template + inline void array_construct(T* memory, std::size_t size, boost::false_type) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } + template + inline void array_construct(T* memory, std::size_t size) { + boost::has_trivial_default_constructor type; + array_construct(memory, size, type); + } +#if defined(BOOST_HAS_RVALUE_REFS) + template + inline void array_construct(T* memory, std::size_t size, T&& value) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(value); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } +#if defined(BOOST_HAS_VARIADIC_TMPL) + template + inline void array_construct(T* memory, std::size_t size, Args&&... args) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(args...); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } +#endif +#endif + template + inline void array_construct_list(T* memory, std::size_t size, const T* list) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i]); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } + template + inline void array_construct_list(T* memory, std::size_t size, const T* list) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } + template + inline void array_construct_noinit(T*, std::size_t, boost::true_type) { + } + template + inline void array_construct_noinit(T* memory, std::size_t size, boost::false_type) { + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T; + } + } catch (...) { + array_destroy(memory, i); + throw; + } + } + template + inline void array_construct_noinit(T* memory, std::size_t size) { + boost::has_trivial_default_constructor type; + array_construct_noinit(memory, size, type); + } + } +} + +#endif diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index b4fd9f6..cf63ecb 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include @@ -141,7 +140,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, p3, M); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -164,7 +163,7 @@ namespace boost { p3 = reinterpret_cast(list); p1 = reinterpret_cast(p2); d2 = get_deleter >(s1); - d2->construct_list(p2, p3, M); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } #if defined(BOOST_HAS_RVALUE_REFS)