diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index bdd8b1f..1ae5cc7 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -19,7 +19,7 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator A1; + typedef boost::detail::as_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; std::size_t n1 = size * boost::detail::array_total::size; T1* p1 = 0; @@ -45,7 +45,7 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator A1; + typedef boost::detail::as_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size @@ -75,7 +75,7 @@ namespace boost { typedef typename boost::detail::array_base::type T2; typedef const T2 T3; typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator A1; + typedef boost::detail::as_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; enum { M = boost::detail::array_total::size @@ -107,7 +107,7 @@ namespace boost { typedef typename boost::detail::array_base::type T2; typedef const T2 T3; typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator A1; + typedef boost::detail::as_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size, @@ -137,7 +137,7 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef boost::detail::ms_noinit_tag R1; - typedef boost::detail::as_allocator A1; + typedef boost::detail::as_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; std::size_t n1 = size * boost::detail::array_total::size; T1* p1 = 0; @@ -159,7 +159,7 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef boost::detail::ms_noinit_tag R1; - typedef boost::detail::as_allocator A1; + typedef boost::detail::as_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp index 79bae59..d342e04 100644 --- a/include/boost/smart_ptr/detail/array_allocator.hpp +++ b/include/boost/smart_ptr/detail/array_allocator.hpp @@ -13,151 +13,129 @@ #include #include #include -#include namespace boost { namespace detail { - template - struct as_size_base; + struct ms_init_tag { }; + struct ms_noinit_tag { }; - template - struct as_size_base - : A { - as_size_base(const A& allocator, std::size_t size_) - : A(allocator), - size(size_ * array_total::size) { - } + template + class ms_allocator_state; - template - as_size_base(const as_size_base& other) - : A(other), - size(other.size) { + template + struct ms_allocator_state { + typedef typename array_base::type type; + + ms_allocator_state(std::size_t size_, + type** result_) + : size(size_ * array_total::size), + result(result_) { } std::size_t size; + + union { + type** result; + type* object; + }; }; - template - struct as_size_base - : A { - as_size_base(const A& allocator) - : A(allocator) { - } + template + struct ms_allocator_state { + typedef typename array_base::type type; - template - as_size_base(const as_size_base& other) - : A(other) { + ms_allocator_state(type** result_) + : result(result_) { } enum { size = array_total::size }; + + union { + type** result; + type* object; + }; }; - struct ms_init_tag { }; - struct ms_noinit_tag { }; - - template - union ms_allocator_state { - ms_allocator_state(T** result_) - : result(result_) { - } - - T** result; - T* object; - }; - - template + template class as_allocator -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - : as_size_base:: - template rebind_alloc > { -#else - : as_size_base::other> { -#endif - template + : public A { + template friend class as_allocator; #if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef typename std::allocator_traits:: - template rebind_alloc YA; - typedef typename std::allocator_traits:: - template rebind_alloc CA; - typedef typename std::allocator_traits:: - template rebind_traits YT; - typedef typename std::allocator_traits:: - template rebind_traits CT; + typedef std::allocator_traits AT; + typedef typename AT::template rebind_alloc CA; + typedef typename AT::template rebind_traits CT; #else - typedef typename A::template rebind::other YA; typedef typename A::template rebind::other CA; #endif - using as_size_base::size; - public: - typedef typename array_base::type type; + typedef A allocator_type; #if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef typename YT::value_type value_type; - typedef typename YT::pointer pointer; - typedef typename YT::const_pointer const_pointer; - typedef typename YT::size_type size_type; - typedef typename YT::difference_type difference_type; - typedef Y& reference; - typedef const Y& const_reference; + typedef typename AT::value_type value_type; + typedef typename AT::pointer pointer; + typedef typename AT::const_pointer const_pointer; + typedef typename AT::void_pointer void_pointer; + typedef typename AT::const_void_pointer const_void_pointer; + typedef typename AT::size_type size_type; + typedef typename AT::difference_type difference_type; #else - typedef typename YA::value_type value_type; - typedef typename YA::pointer pointer; - typedef typename YA::const_pointer const_pointer; - typedef typename YA::size_type size_type; - typedef typename YA::difference_type difference_type; - typedef typename YA::reference reference; - typedef typename YA::const_reference const_reference; + typedef typename A::value_type value_type; + typedef typename A::pointer pointer; + typedef typename A::const_pointer const_pointer; + typedef typename A::size_type size_type; + typedef typename A::difference_type difference_type; + typedef typename A::reference reference; + typedef typename A::const_reference const_reference; + typedef void* void_pointer; + typedef const void* const_void_pointer; #endif template struct rebind { - typedef as_allocator other; +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef as_allocator, T, R> other; +#else + typedef as_allocator::other, T, R> other; +#endif }; + typedef typename array_base::type type; + as_allocator(const A& allocator, type** result) - : as_size_base(allocator), + : A(allocator), data(result) { } - as_allocator(const A& allocator, std::size_t size_, + as_allocator(const A& allocator, std::size_t size, type** result) - : as_size_base(allocator, size_), - data(result) { + : A(allocator), + data(size, result) { } template - as_allocator(const as_allocator& other) - : as_size_base(other), + as_allocator(const as_allocator& other) + : A(other.allocator()), data(other.data) { } -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - size_type max_size() const { - return YT::max_size(*this); - } -#else - using YA::address; - using YA::max_size; -#endif - - pointer allocate(size_type count, const void* value = 0) { + pointer allocate(size_type count, const_void_pointer hint = 0) { enum { M = boost::alignment_of::value }; std::size_t n1 = count * sizeof(value_type); - std::size_t n2 = size * sizeof(type) + M - 1; - CA ca(*this); + std::size_t n2 = data.size * sizeof(type) + M; + CA ca(allocator()); #if !defined(BOOST_NO_CXX11_ALLOCATOR) - void* p1 = CT::allocate(ca, n1 + n2, value); + void* p1 = CT::allocate(ca, n1 + n2, hint); #else - void* p1 = ca.allocate(n1 + n2, value); + void* p1 = ca.allocate(n1 + n2, hint); #endif void* p2 = static_cast(p1) + n1; p2 = sp_align(M, p2); @@ -170,51 +148,18 @@ namespace boost { M = boost::alignment_of::value }; std::size_t n1 = count * sizeof(value_type); - std::size_t n2 = size * sizeof(type) + M - 1; + std::size_t n2 = data.size * sizeof(type) + M; char* p1 = reinterpret_cast(memory); - CA ca(*this); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - CT::deallocate(ca, p1, n1 + n2); -#else + CA ca(allocator()); ca.deallocate(p1, n1 + n2); -#endif } - template - void construct(U* memory, const_reference value) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - YT::construct(*this, memory, value); -#else - YA::construct(memory, value); -#endif + const A& allocator() const { + return static_cast(*this); } - template - void destroy(U* memory) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - YT::destroy(*this, memory); -#else - YA::destroy(memory); -#endif - } - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ - !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ - !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template - void construct(U* memory, Args&&... args) { - YT::construct(*this, memory, std::forward(args)...); - } -#endif - - template - bool operator==(const as_allocator& other) const { - return true; - } - - template - bool operator!=(const as_allocator& other) const { - return !(*this == other); + A& allocator() { + return static_cast(*this); } void set(type* memory) { @@ -231,44 +176,37 @@ namespace boost { private: void free(ms_init_tag) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - as_destroy(*this, data.object, size); + as_destroy(allocator(), data.object, data.size); #else - ms_destroy(data.object, size); + ms_destroy(data.object, data.size); #endif } void free(ms_noinit_tag) { - ms_destroy(data.object, size); + ms_destroy(data.object, data.size); } - ms_allocator_state data; + ms_allocator_state data; }; - template - struct ms_size_base; + template + bool operator==(const as_allocator& a1, + const as_allocator& a2) { + return a1.allocator() == a2.allocator(); + } - template - struct ms_size_base { - ms_size_base(std::size_t size_) - : size(size_ * array_total::size) { - } + template + bool operator!=(const as_allocator& a1, + const as_allocator& a2) { + return a1.allocator() != a2.allocator(); + } - std::size_t size; - }; + template + class ms_allocator; - template - struct ms_size_base { - enum { - size = array_total::size - }; - }; - - template - class ms_allocator - : ms_size_base { - using ms_size_base::size; - - template + template + class ms_allocator { + template friend class ms_allocator; public: @@ -284,22 +222,38 @@ namespace boost { template struct rebind { - typedef ms_allocator other; + typedef ms_allocator other; }; ms_allocator(type** result) : data(result) { } - ms_allocator(std::size_t size_, type** result) - : ms_size_base(size_), - data(result) { + ms_allocator(std::size_t size, type** result) + : data(size, result) { } template - ms_allocator(const ms_allocator& other) - : ms_size_base(other), - data(other.data) { + ms_allocator(const ms_allocator& other) + : data(other.data) { + } + + pointer allocate(size_type count, const void* = 0) { + enum { + M = boost::alignment_of::value + }; + std::size_t n1 = count * sizeof(Y); + std::size_t n2 = data.size * sizeof(type) + M; + void* p1 = ::operator new(n1 + n2); + void* p2 = static_cast(p1) + n1; + p2 = sp_align(M, p2); + *data.result = static_cast(p2); + return static_cast(p1); + } + + void deallocate(pointer memory, size_type) { + void* p1 = memory; + ::operator delete(p1); } #if defined(BOOST_NO_CXX11_ALLOCATOR) @@ -310,78 +264,50 @@ namespace boost { const_pointer address(const_reference value) const { return &value; } -#endif size_type max_size() const { enum { - N = static_cast(-1) / sizeof(value_type) + N = static_cast(-1) / sizeof(Y) }; return N; } - pointer allocate(size_type count, const void* = 0) { - enum { - M = boost::alignment_of::value - }; - std::size_t n1 = count * sizeof(value_type); - std::size_t n2 = size * sizeof(type) + M - 1; - void* p1 = ::operator new(n1 + n2); - void* p2 = static_cast(p1) + n1; - p2 = sp_align(M, p2); - *data.result = static_cast(p2); - return static_cast(p1); - } - - void deallocate(pointer memory, size_type) { + void construct(pointer memory, const_reference value) { void* p1 = memory; - ::operator delete(p1); + ::new(p1) Y(value); } - template - void construct(U* memory, const_reference value) { - void* p1 = memory; - ::new(p1) U(value); - } - - template - void destroy(U* memory) { - memory->~U(); - } - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ - !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ - !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template - void construct(U* memory, Args&&... args) { - void* p1 = memory; - ::new(p1) U(std::forward(args)...); + void destroy(pointer memory) { + memory->~Y(); } #endif - template - bool operator==(const ms_allocator&) const { - return true; - } - - template - bool operator!=(const ms_allocator& other) const { - return !(*this == other); - } - void set(type* memory) { data.object = memory; } void operator()() { if (data.object) { - ms_destroy(data.object, size); + ms_destroy(data.object, data.size); } } private: - ms_allocator_state data; + ms_allocator_state data; }; + template + bool operator==(const ms_allocator&, + const ms_allocator&) { + return true; + } + + template + bool operator!=(const ms_allocator&, + const ms_allocator&) { + return false; + } + class ms_in_allocator_tag { public: void operator()(const void*) { diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 8c2c5d0..c48f507 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -18,8 +18,7 @@ namespace boost { make_shared(std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; std::size_t n1 = size * boost::detail::array_total::size; T1* p1 = 0; @@ -40,8 +39,7 @@ namespace boost { make_shared() { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size @@ -66,8 +64,7 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; enum { M = boost::detail::array_total::size @@ -93,8 +90,7 @@ namespace boost { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; typedef const T2 T3; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; enum { M = boost::detail::array_total::size, @@ -119,8 +115,7 @@ namespace boost { make_shared_noinit(std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_noinit_tag R1; - typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; std::size_t n1 = size * boost::detail::array_total::size; T1* p1 = 0; @@ -141,8 +136,7 @@ namespace boost { make_shared_noinit() { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_noinit_tag R1; - typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_allocator A1; typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size diff --git a/test/allocate_shared_array_construct_test.cpp b/test/allocate_shared_array_construct_test.cpp index ee1c812..fe9fe3f 100644 --- a/test/allocate_shared_array_construct_test.cpp +++ b/test/allocate_shared_array_construct_test.cpp @@ -15,13 +15,6 @@ class creator { public: typedef T value_type; -#if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) - template - struct rebind { - typedef creator other; - }; -#endif - creator() { }