Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / smart_ptr / allocate_shared_array.hpp
index 1ae5cc7..b43b43d 100644 (file)
 /*
- * Copyright (c) 2012-2014 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)
- */
+Copyright 2012-2017 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_SHARED_ARRAY_HPP
 #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
 
-#include <boost/smart_ptr/detail/array_count_impl.hpp>
-#include <boost/smart_ptr/detail/sp_if_array.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
 
 namespace boost {
-    template<class T, class A>
-    inline typename boost::detail::sp_if_array<T>::type
-    allocate_shared(const A& allocator, std::size_t size) {
-        typedef typename boost::detail::array_inner<T>::type T1;
-        typedef typename boost::detail::array_base<T1>::type T2;
-        typedef boost::detail::ms_init_tag R1;
-        typedef boost::detail::as_allocator<A, T, R1> A1;
-        typedef boost::detail::ms_in_allocator_tag D1;
-        std::size_t n1 = size * boost::detail::array_total<T1>::size;
-        T1* p1 = 0;
-        T2* p2 = 0;
-        D1 d1;
-        A1 a1(allocator, size, &p2);
-        shared_ptr<T> s1(p1, d1, a1);
-        A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
-        a2->set(0);
+namespace detail {
+
+template<class>
+struct sp_if_array { };
+
+template<class T>
+struct sp_if_array<T[]> {
+    typedef boost::shared_ptr<T[]> type;
+};
+
+template<class>
+struct sp_if_size_array { };
+
+template<class T, std::size_t N>
+struct sp_if_size_array<T[N]> {
+    typedef boost::shared_ptr<T[N]> type;
+};
+
+template<class>
+struct sp_array_element { };
+
+template<class T>
+struct sp_array_element<T[]> {
+    typedef T type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_element<T[N]> {
+    typedef T type;
+};
+
+template<class T>
+struct sp_array_scalar {
+    typedef T type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<T[N]> {
+    typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<const T[N]> {
+    typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<volatile T[N]> {
+    typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T, std::size_t N>
+struct sp_array_scalar<const volatile T[N]> {
+    typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<T[]> {
+    typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<const T[]> {
+    typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<volatile T[]> {
+    typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_scalar<const volatile T[]> {
+    typedef typename sp_array_scalar<T>::type type;
+};
+
+template<class T>
+struct sp_array_count {
+    enum {
+        value = 1
+    };
+};
+
+template<class T, std::size_t N>
+struct sp_array_count<T[N]> {
+    enum {
+        value = N * sp_array_count<T>::value
+    };
+};
+
+template<class T>
+struct sp_array_count<T[]> { };
+
+template<class D, class T>
+inline D*
+sp_get_deleter(const
+    boost::shared_ptr<T>& value) BOOST_NOEXCEPT_OR_NOTHROW
+{
+    return static_cast<D*>(value._internal_get_untyped_deleter());
+}
+
+template<std::size_t N, std::size_t A>
+struct sp_array_storage {
+    union type {
+        char value[N];
+        typename boost::type_with_alignment<A>::type other;
+    };
+};
+
+template<std::size_t N, std::size_t M>
+struct sp_max_size {
+    enum {
+        value = N < M ? M : N
+    };
+};
+
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-        boost::detail::as_init(allocator, p2, n1);
+template<class A, class T>
+struct sp_bind_allocator {
+    typedef typename std::allocator_traits<A>::template
+        rebind_alloc<T> type;
+};
 #else
-        boost::detail::ms_init(p2, n1);
+template<class A, class T>
+struct sp_bind_allocator {
+    typedef typename A::template rebind<T>::other type;
+};
 #endif
-        a2->set(p2);
-        p1 = reinterpret_cast<T1*>(p2);
-        return shared_ptr<T>(s1, p1);
-    }
-
-    template<class T, class A>
-    inline typename boost::detail::sp_if_size_array<T>::type
-    allocate_shared(const A& allocator) {
-        typedef typename boost::detail::array_inner<T>::type T1;
-        typedef typename boost::detail::array_base<T1>::type T2;
-        typedef boost::detail::ms_init_tag R1;
-        typedef boost::detail::as_allocator<A, T, R1> A1;
-        typedef boost::detail::ms_in_allocator_tag D1;
-        enum {
-            N = boost::detail::array_total<T>::size
-        };
-        T1* p1 = 0;
-        T2* p2 = 0;
-        D1 d1;
-        A1 a1(allocator, &p2);
-        shared_ptr<T> s1(p1, d1, a1);
-        A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
-        a2->set(0);
+
+template<bool, class = void>
+struct sp_enable { };
+
+template<class T>
+struct sp_enable<true, T> {
+    typedef T type;
+};
+
+template<class T>
+inline
+typename sp_enable<boost::has_trivial_destructor<T>::value>::type
+sp_array_destroy(T*, std::size_t) BOOST_NOEXCEPT { }
+
+template<class T>
+inline
+typename sp_enable<!boost::has_trivial_destructor<T>::value>::type
+sp_array_destroy(T* storage, std::size_t size)
+{
+    while (size > 0) {
+        storage[--size].~T();
+    }
+}
+
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-        boost::detail::as_init(allocator, p2, N);
+template<class A, class T>
+inline void
+sp_array_destroy(A& allocator, T* storage, std::size_t size)
+{
+    while (size > 0) {
+        std::allocator_traits<A>::destroy(allocator, &storage[--size]);
+    }
+}
+#endif
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<class T>
+inline
+typename sp_enable<boost::has_trivial_constructor<T>::value ||
+    boost::has_trivial_destructor<T>::value>::type
+sp_array_construct(T* storage, std::size_t size)
+{
+    for (std::size_t i = 0; i < size; ++i) {
+        ::new(static_cast<void*>(storage + i)) T();
+    }
+}
+
+template<class T>
+inline
+typename sp_enable<!boost::has_trivial_constructor<T>::value &&
+    !boost::has_trivial_destructor<T>::value>::type
+sp_array_construct(T* storage, std::size_t size)
+{
+    std::size_t i = 0;
+    try {
+        for (; i < size; ++i) {
+            ::new(static_cast<void*>(storage + i)) T();
+        }
+    } catch (...) {
+        while (i > 0) {
+            storage[--i].~T();
+        }
+        throw;
+    }
+}
+
+template<class T>
+inline void
+sp_array_construct(T* storage, std::size_t size, const T* list,
+    std::size_t count)
+{
+    std::size_t i = 0;
+    try {
+        for (; i < size; ++i) {
+            ::new(static_cast<void*>(storage + i)) T(list[i % count]);
+        }
+    } catch (...) {
+        while (i > 0) {
+            storage[--i].~T();
+        }
+        throw;
+    }
+}
 #else
-        boost::detail::ms_init(p2, N);
+template<class T>
+inline void
+sp_array_construct(T* storage, std::size_t size)
+{
+    for (std::size_t i = 0; i < size; ++i) {
+        ::new(static_cast<void*>(storage + i)) T();
+    }
+}
+
+template<class T>
+inline void
+sp_array_construct(T* storage, std::size_t size, const T* list,
+    std::size_t count)
+{
+    for (std::size_t i = 0; i < size; ++i) {
+        ::new(static_cast<void*>(storage + i)) T(list[i % count]);
+    }
+}
 #endif
-        a2->set(p2);
-        p1 = reinterpret_cast<T1*>(p2);
-        return shared_ptr<T>(s1, p1);
-    }
-
-    template<class T, class A>
-    inline typename boost::detail::sp_if_array<T>::type
-    allocate_shared(const A& allocator, std::size_t size,
-        const typename boost::detail::array_inner<T>::type& value) {
-        typedef typename boost::detail::array_inner<T>::type T1;
-        typedef typename boost::detail::array_base<T1>::type T2;
-        typedef const T2 T3;
-        typedef boost::detail::ms_init_tag R1;
-        typedef boost::detail::as_allocator<A, T, R1> A1;
-        typedef boost::detail::ms_in_allocator_tag D1;
-        enum {
-            M = boost::detail::array_total<T1>::size
-        };
-        std::size_t n1 = M * size;
-        T1* p1 = 0;
-        T2* p2 = 0;
-        T3* p3 = reinterpret_cast<T3*>(&value);
-        D1 d1;
-        A1 a1(allocator, size, &p2);
-        shared_ptr<T> s1(p1, d1, a1);
-        A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
-        a2->set(0);
+
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-        boost::detail::as_init<T2, A, M>(allocator, p2, n1, p3);
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<class A, class T>
+inline void
+sp_array_construct(A& allocator, T* storage, std::size_t size)
+{
+    std::size_t i = 0;
+    try {
+        for (i = 0; i < size; ++i) {
+            std::allocator_traits<A>::construct(allocator, storage + i);
+        }
+    } catch (...) {
+        sp_array_destroy(allocator, storage, i);
+        throw;
+    }
+}
+
+template<class A, class T>
+inline void
+sp_array_construct(A& allocator, T* storage, std::size_t size,
+    const T* list, std::size_t count)
+{
+    std::size_t i = 0;
+    try {
+        for (i = 0; i < size; ++i) {
+            std::allocator_traits<A>::construct(allocator, storage + i,
+                list[i % count]);
+        }
+    } catch (...) {
+        sp_array_destroy(allocator, storage, i);
+        throw;
+    }
+}
 #else
-        boost::detail::ms_init<T2, M>(p2, n1, p3);
+template<class A, class T>
+inline void
+sp_array_construct(A& allocator, T* storage, std::size_t size)
+{
+    for (std::size_t i = 0; i < size; ++i) {
+        std::allocator_traits<A>::construct(allocator, storage + i);
+    }
+}
+
+template<class A, class T>
+inline void
+sp_array_construct(A& allocator, T* storage, std::size_t size,
+    const T* list, std::size_t count)
+{
+    for (std::size_t i = 0; i < size; ++i) {
+        std::allocator_traits<A>::construct(allocator, storage + i,
+            list[i % count]);
+    }
+}
+#endif
 #endif
-        a2->set(p2);
-        p1 = reinterpret_cast<T1*>(p2);
-        return shared_ptr<T>(s1, p1);
-    }
-
-    template<class T, class A>
-    inline typename boost::detail::sp_if_size_array<T>::type
-    allocate_shared(const A& allocator, 
-        const typename boost::detail::array_inner<T>::type& value) {
-        typedef typename boost::detail::array_inner<T>::type T1;
-        typedef typename boost::detail::array_base<T1>::type T2;
-        typedef const T2 T3;
-        typedef boost::detail::ms_init_tag R1;
-        typedef boost::detail::as_allocator<A, T, R1> A1;
-        typedef boost::detail::ms_in_allocator_tag D1;
-        enum {
-            N = boost::detail::array_total<T>::size,
-            M = boost::detail::array_total<T1>::size
-        };
-        T1* p1 = 0;
-        T2* p2 = 0;
-        T3* p3 = reinterpret_cast<T3*>(&value);
-        D1 d1;
-        A1 a1(allocator, &p2);
-        shared_ptr<T> s1(p1, d1, a1);
-        A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
-        a2->set(0);
+
+template<class T>
+inline
+typename sp_enable<boost::has_trivial_constructor<T>::value>::type
+sp_array_default(T*, std::size_t) BOOST_NOEXCEPT { }
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+template<class T>
+inline
+typename sp_enable<!boost::has_trivial_constructor<T>::value &&
+    boost::has_trivial_destructor<T>::value>::type
+sp_array_default(T* storage, std::size_t size)
+{
+    for (std::size_t i = 0; i < size; ++i) {
+        ::new(static_cast<void*>(storage + i)) T;
+    }
+}
+
+template<class T>
+inline
+typename sp_enable<!boost::has_trivial_constructor<T>::value &&
+    !boost::has_trivial_destructor<T>::value>::type
+sp_array_default(T* storage, std::size_t size)
+{
+    std::size_t i = 0;
+    try {
+        for (; i < size; ++i) {
+            ::new(static_cast<void*>(storage + i)) T;
+        }
+    } catch (...) {
+        while (i > 0) {
+            storage[--i].~T();
+        }
+        throw;
+    }
+}
+#else
+template<class T>
+inline
+typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
+sp_array_default(T* storage, std::size_t size)
+{
+    for (std::size_t i = 0; i < size; ++i) {
+        ::new(static_cast<void*>(storage + i)) T;
+    }
+}
+#endif
+
+template<class T, std::size_t N>
+struct sp_less_align {
+    enum {
+        value = (boost::alignment_of<T>::value) < N
+    };
+};
+
+template<class T, std::size_t N>
+BOOST_CONSTEXPR inline
+typename sp_enable<sp_less_align<T, N>::value, std::size_t>::type
+sp_align(std::size_t size) BOOST_NOEXCEPT
+{
+    return (sizeof(T) * size + N - 1) & ~(N - 1);
+}
+
+template<class T, std::size_t N>
+BOOST_CONSTEXPR inline
+typename sp_enable<!sp_less_align<T, N>::value, std::size_t>::type
+sp_align(std::size_t size) BOOST_NOEXCEPT
+{
+    return sizeof(T) * size;
+}
+
+template<class T>
+BOOST_CONSTEXPR inline std::size_t
+sp_types(std::size_t size) BOOST_NOEXCEPT
+{
+    return (size + sizeof(T) - 1) / sizeof(T);
+}
+
+template<class T, std::size_t N>
+class sp_size_array_deleter {
+public:
+    template<class U>
+    static void operator_fn(U) BOOST_NOEXCEPT { }
+
+    sp_size_array_deleter() BOOST_NOEXCEPT
+        : enabled_(false) { }
+
+    template<class A>
+    sp_size_array_deleter(const A&) BOOST_NOEXCEPT
+        : enabled_(false) { }
+
+    sp_size_array_deleter(const sp_size_array_deleter&) BOOST_NOEXCEPT
+        : enabled_(false) { }
+
+    ~sp_size_array_deleter() {
+        if (enabled_) {
+            sp_array_destroy(reinterpret_cast<T*>(&storage_), N);
+        }
+    }
+
+    template<class U>
+    void operator()(U) {
+        if (enabled_) {
+            sp_array_destroy(reinterpret_cast<T*>(&storage_), N);
+            enabled_ = false;
+        }
+    }
+
+    void* construct() {
+        sp_array_construct(reinterpret_cast<T*>(&storage_), N);
+        enabled_ = true;
+        return &storage_;
+    }
+
+    void* construct(const T* list, std::size_t count) {
+        sp_array_construct(reinterpret_cast<T*>(&storage_), N,
+            list, count);
+        enabled_ = true;
+        return &storage_;
+    }
+
+    void* construct_default() {
+        sp_array_default(reinterpret_cast<T*>(&storage_), N);
+        enabled_ = true;
+        return &storage_;
+    }
+
+private:
+    bool enabled_;
+    typename sp_array_storage<sizeof(T) * N,
+        boost::alignment_of<T>::value>::type storage_;
+};
+
 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
-        boost::detail::as_init<T2, A, M>(allocator, p2, N, p3);
+template<class T, std::size_t N, class A>
+class sp_size_array_destroyer {
+public:
+    template<class U>
+    static void operator_fn(U) BOOST_NOEXCEPT { }
+
+    template<class U>
+    sp_size_array_destroyer(const U& allocator) BOOST_NOEXCEPT
+        : allocator_(allocator),
+          enabled_(false) { }
+
+    sp_size_array_destroyer(const sp_size_array_destroyer& other)
+        BOOST_NOEXCEPT
+        : allocator_(other.allocator_),
+          enabled_(false) { }
+
+    ~sp_size_array_destroyer() {
+        if (enabled_) {
+            sp_array_destroy(allocator_,
+                reinterpret_cast<T*>(&storage_), N);
+        }
+    }
+
+    template<class U>
+    void operator()(U) {
+        if (enabled_) {
+            sp_array_destroy(allocator_,
+                reinterpret_cast<T*>(&storage_), N);
+            enabled_ = false;
+        }
+    }
+
+    void* construct() {
+        sp_array_construct(allocator_,
+            reinterpret_cast<T*>(&storage_), N);
+        enabled_ = true;
+        return &storage_;
+    }
+
+    void* construct(const T* list, std::size_t count) {
+        sp_array_construct(allocator_,
+            reinterpret_cast<T*>(&storage_), N, list, count);
+        enabled_ = true;
+        return &storage_;
+    }
+
+    const A& allocator() const BOOST_NOEXCEPT {
+        return allocator_;
+    }
+
+private:
+    typename sp_array_storage<sizeof(T) * N,
+        boost::alignment_of<T>::value>::type storage_;
+    A allocator_;
+    bool enabled_;
+};
+#endif
+
+template<class T>
+class sp_array_deleter {
+public:
+    template<class U>
+    static void operator_fn(U) BOOST_NOEXCEPT { }
+
+    sp_array_deleter(std::size_t size) BOOST_NOEXCEPT
+        : address_(0),
+          size_(size) { }
+
+    template<class A>
+    sp_array_deleter(const A& allocator) BOOST_NOEXCEPT
+        : address_(0),
+          size_(allocator.size()) { }
+
+    template<class A>
+    sp_array_deleter(const A&, std::size_t size) BOOST_NOEXCEPT
+        : address_(0),
+          size_(size) { }
+
+    sp_array_deleter(const sp_array_deleter& other) BOOST_NOEXCEPT
+        : address_(0),
+          size_(other.size_) { }
+
+    ~sp_array_deleter() {
+        if (address_) {
+            sp_array_destroy(static_cast<T*>(address_), size_);
+        }
+    }
+
+    template<class U>
+    void operator()(U) {
+        if (address_) {
+            sp_array_destroy(static_cast<T*>(address_), size_);
+            address_ = 0;
+        }
+    }
+
+    void construct(T* address) {
+        sp_array_construct(address, size_);
+        address_ = address;
+    }
+
+    void construct(T* address, const T* list, std::size_t count) {
+        sp_array_construct(address, size_, list, count);
+        address_ = address;
+    }
+
+    void construct_default(T* address) {
+        sp_array_default(address, size_);
+        address_ = address;
+    }
+
+    std::size_t size() const BOOST_NOEXCEPT {
+        return size_;
+    }
+
+private:
+    void* address_;
+    std::size_t size_;
+};
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<class T, class A>
+class sp_array_destroyer {
+public:
+    template<class U>
+    static void operator_fn(U) BOOST_NOEXCEPT { }
+
+    template<class U>
+    sp_array_destroyer(const U& allocator, std::size_t size)
+        BOOST_NOEXCEPT
+        : allocator_(allocator),
+          size_(size),
+          address_(0) { }
+
+    template<class U>
+    sp_array_destroyer(const U& allocator) BOOST_NOEXCEPT
+        : allocator_(allocator.allocator()),
+          size_(allocator.size()),
+          address_(0) { }
+
+    sp_array_destroyer(const sp_array_destroyer& other) BOOST_NOEXCEPT
+        : allocator_(other.allocator_),
+          size_(other.size_),
+          address_(0) { }
+
+    ~sp_array_destroyer() {
+        if (address_) {
+            sp_array_destroy(allocator_, static_cast<T*>(address_),
+                size_);
+        }
+    }
+
+    template<class U>
+    void operator()(U) {
+        if (address_) {
+            sp_array_destroy(allocator_, static_cast<T*>(address_),
+                size_);
+            address_ = 0;
+        }
+    }
+
+    void construct(T* address) {
+        sp_array_construct(allocator_, address, size_);
+        address_ = address;
+    }
+
+    void construct(T* address, const T* list, std::size_t count) {
+        sp_array_construct(allocator_, address, size_, list, count);
+        address_ = address;
+    }
+
+    const A& allocator() const BOOST_NOEXCEPT {
+        return allocator_;
+    }
+
+    std::size_t size() const BOOST_NOEXCEPT {
+        return size_;
+    }
+
+private:
+    A allocator_;
+    std::size_t size_;
+    void* address_;
+};
+#endif
+
+template<class T, class A>
+class sp_array_allocator {
+    template<class U, class V>
+    friend class sp_array_allocator;
+
+public:
+    typedef typename A::value_type value_type;
+
+private:
+    enum {
+        alignment = sp_max_size<boost::alignment_of<T>::value,
+            boost::alignment_of<value_type>::value>::value
+    };
+
+    typedef typename boost::type_with_alignment<alignment>::type type;
+    typedef typename sp_bind_allocator<A, type>::type type_allocator;
+
+public:
+    template<class U>
+    struct rebind {
+        typedef sp_array_allocator<T,
+            typename sp_bind_allocator<A, U>::type> other;
+    };
+
+    sp_array_allocator(const A& allocator, std::size_t size,
+        void** result) BOOST_NOEXCEPT
+        : allocator_(allocator),
+          size_(size),
+          result_(result) { }
+
+    sp_array_allocator(const A& allocator, std::size_t size)
+        BOOST_NOEXCEPT
+        : allocator_(allocator),
+          size_(size) { }
+
+    template<class U>
+    sp_array_allocator(const sp_array_allocator<T, U>& other)
+        BOOST_NOEXCEPT
+        : allocator_(other.allocator_),
+          size_(other.size_),
+          result_(other.result_) { }
+
+    value_type* allocate(std::size_t count) {
+        type_allocator allocator(allocator_);
+        std::size_t node = sp_align<value_type, alignment>(count);
+        std::size_t size = sp_types<type>(node + sizeof(T) * size_);
+        type* address = allocator.allocate(size);
+        *result_ = reinterpret_cast<char*>(address) + node;
+        return reinterpret_cast<value_type*>(address);
+    }
+
+    void deallocate(value_type* value, std::size_t count) {
+        type_allocator allocator(allocator_);
+        std::size_t node = sp_align<value_type, alignment>(count);
+        std::size_t size = sp_types<type>(node + sizeof(T) * size_);
+        allocator.deallocate(reinterpret_cast<type*>(value), size);
+    }
+
+    const A& allocator() const BOOST_NOEXCEPT {
+        return allocator_;
+    }
+
+    std::size_t size() const BOOST_NOEXCEPT {
+        return size_;
+    }
+
+private:
+    A allocator_;
+    std::size_t size_;
+    void** result_;
+};
+
+template<class T, class U, class V>
+inline bool
+operator==(const sp_array_allocator<T, U>& first,
+    const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT
+{
+    return first.allocator() == second.allocator() &&
+        first.size() == second.size();
+}
+
+template<class T, class U, class V>
+inline bool
+operator!=(const sp_array_allocator<T, U>& first,
+    const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT
+{
+    return !(first == second);
+}
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<class A, class T, std::size_t N>
+struct sp_select_size_deleter {
+    typedef sp_size_array_destroyer<T, N,
+        typename sp_bind_allocator<A, T>::type> type;
+};
+
+template<class U, class T, std::size_t N>
+struct sp_select_size_deleter<std::allocator<U>, T, N> {
+    typedef sp_size_array_deleter<T, N> type;
+};
+
+template<class A, class T>
+struct sp_select_deleter {
+    typedef sp_array_destroyer<T,
+        typename sp_bind_allocator<A, T>::type> type;
+};
+
+template<class U, class T>
+struct sp_select_deleter<std::allocator<U>, T> {
+    typedef sp_array_deleter<T> type;
+};
 #else
-        boost::detail::ms_init<T2,  M>(p2, N, p3);
+template<class, class T, std::size_t N>
+struct sp_select_size_deleter {
+    typedef sp_size_array_deleter<T, N> type;
+};
+
+template<class, class T>
+struct sp_select_deleter {
+    typedef sp_array_deleter<T> type;
+};
+#endif
+
+template<class P, class T, std::size_t N, class A>
+class sp_counted_impl_pda<P, sp_size_array_deleter<T, N>, A>
+    : public sp_counted_base {
+public:
+    typedef sp_size_array_deleter<T, N> deleter_type;
+
+private:
+    typedef sp_counted_impl_pda<P, deleter_type, A> type;
+    typedef typename sp_bind_allocator<A, type>::type deallocator;
+
+public:
+    sp_counted_impl_pda(P, const deleter_type&, const A& allocator)
+        : deleter_(allocator),
+          allocator_(allocator) { }
+
+    sp_counted_impl_pda(P, const A& allocator)
+        : deleter_(allocator) { }
+
+    void dispose() {
+        deleter_(0);
+    }
+
+    void destroy() {
+        deallocator allocator(allocator_);
+        this->~type();
+        allocator.deallocate(this, 1);
+    }
+
+    void* get_deleter(const sp_typeinfo&) {
+        return &reinterpret_cast<char&>(deleter_);
+    }
+
+    void* get_untyped_deleter() {
+        return &reinterpret_cast<char&>(deleter_);
+    }
+
+private:
+    deleter_type deleter_;
+    A allocator_;
+};
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<class P, class T, std::size_t N, class U, class A>
+class sp_counted_impl_pda<P, sp_size_array_destroyer<T, N, U>, A>
+    : public sp_counted_base {
+public:
+    typedef sp_size_array_destroyer<T, N, U> deleter_type;
+
+private:
+    typedef sp_counted_impl_pda<P, deleter_type, A> type;
+    typedef typename sp_bind_allocator<A, type>::type deallocator;
+
+public:
+    sp_counted_impl_pda(P, const deleter_type&, const A& allocator)
+        : deleter_(allocator) { }
+
+    sp_counted_impl_pda(P, const A& allocator)
+        : deleter_(allocator) { }
+
+    void dispose() {
+        deleter_(0);
+    }
+
+    void destroy() {
+        deallocator allocator(deleter_.allocator());
+        this->~type();
+        allocator.deallocate(this, 1);
+    }
+
+    void* get_deleter(const sp_typeinfo&) {
+        return &reinterpret_cast<char&>(deleter_);
+    }
+
+    void* get_untyped_deleter() {
+        return &reinterpret_cast<char&>(deleter_);
+    }
+
+private:
+    deleter_type deleter_;
+};
 #endif
-        a2->set(p2);
-        p1 = reinterpret_cast<T1*>(p2);
-        return shared_ptr<T>(s1, p1);
-    }
-
-    template<class T, class A>
-    inline typename boost::detail::sp_if_array<T>::type
-    allocate_shared_noinit(const A& allocator, std::size_t size) {
-        typedef typename boost::detail::array_inner<T>::type T1;
-        typedef typename boost::detail::array_base<T1>::type T2;
-        typedef boost::detail::ms_noinit_tag R1;
-        typedef boost::detail::as_allocator<A, T, R1> A1;
-        typedef boost::detail::ms_in_allocator_tag D1;
-        std::size_t n1 = size * boost::detail::array_total<T1>::size;
-        T1* p1 = 0;
-        T2* p2 = 0;
-        D1 d1;
-        A1 a1(allocator, size, &p2);
-        shared_ptr<T> s1(p1, d1, a1);
-        A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
-        a2->set(0);
-        boost::detail::ms_noinit(p2, n1);
-        a2->set(p2);
-        p1 = reinterpret_cast<T1*>(p2);
-        return shared_ptr<T>(s1, p1);
-    }
-
-    template<class T, class A>
-    inline typename boost::detail::sp_if_size_array<T>::type
-    allocate_shared_noinit(const A& allocator) {
-        typedef typename boost::detail::array_inner<T>::type T1;
-        typedef typename boost::detail::array_base<T1>::type T2;
-        typedef boost::detail::ms_noinit_tag R1;
-        typedef boost::detail::as_allocator<A, T, R1> A1;
-        typedef boost::detail::ms_in_allocator_tag D1;
-        enum {
-            N = boost::detail::array_total<T>::size
-        };
-        T1* p1 = 0;
-        T2* p2 = 0;
-        D1 d1;
-        A1 a1(allocator, &p2);
-        shared_ptr<T> s1(p1, d1, a1);
-        A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
-        a2->set(0);
-        boost::detail::ms_noinit(p2, N);
-        a2->set(p2);
-        p1 = reinterpret_cast<T1*>(p2);
-        return shared_ptr<T>(s1, p1);
+
+template<class P, class T, class A>
+class sp_counted_impl_pda<P, sp_array_deleter<T>,
+    sp_array_allocator<T, A> >
+    : public sp_counted_base {
+public:
+    typedef sp_array_deleter<T> deleter_type;
+    typedef sp_array_allocator<T, A> allocator_type;
+
+private:
+    typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type;
+    typedef sp_array_allocator<T,
+        typename sp_bind_allocator<A, type>::type> deallocator;
+
+public:
+    sp_counted_impl_pda(P, const deleter_type&,
+        const allocator_type& allocator)
+        : deleter_(allocator),
+          allocator_(allocator.allocator()) { }
+
+    sp_counted_impl_pda(P, const allocator_type& allocator)
+        : deleter_(allocator),
+          allocator_(allocator.allocator()) { }
+
+    void dispose() {
+        deleter_(0);
+    }
+
+    void destroy() {
+        deallocator allocator(allocator_, deleter_.size());
+        this->~type();
+        allocator.deallocate(this, 1);
+    }
+
+    void* get_deleter(const sp_typeinfo&) {
+        return &reinterpret_cast<char&>(deleter_);
+    }
+
+    void* get_untyped_deleter() {
+        return &reinterpret_cast<char&>(deleter_);
+    }
+
+private:
+    deleter_type deleter_;
+    A allocator_;
+};
+
+#if !defined(BOOST_NO_CXX11_ALLOCATOR)
+template<class P, class T, class U, class A>
+class sp_counted_impl_pda<P, sp_array_destroyer<T, U>,
+    sp_array_allocator<T, A> >
+    : public sp_counted_base {
+public:
+    typedef sp_array_destroyer<T, U> deleter_type;
+    typedef sp_array_allocator<T, A> allocator_type;
+
+private:
+    typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type;
+    typedef sp_array_allocator<T,
+        typename sp_bind_allocator<A, type>::type> deallocator;
+
+public:
+    sp_counted_impl_pda(P, const deleter_type&,
+        const allocator_type& allocator)
+        : deleter_(allocator) { }
+
+    sp_counted_impl_pda(P, const allocator_type& allocator)
+        : deleter_(allocator) { }
+
+    void dispose() {
+        deleter_(0);
+    }
+
+    void destroy() {
+        deallocator allocator(deleter_.allocator(), deleter_.size());
+        this->~type();
+        allocator.deallocate(this, 1);
+    }
+
+    void* get_deleter(const sp_typeinfo&) {
+        return &reinterpret_cast<char&>(deleter_);
+    }
+
+    void* get_untyped_deleter() {
+        return &reinterpret_cast<char&>(deleter_);
     }
+
+private:
+    deleter_type deleter_;
+};
+#endif
+
+} /* detail */
+
+template<class T, class A>
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared(const A& allocator)
+{
+    typedef typename detail::sp_array_element<T>::type type;
+    typedef typename detail::sp_array_scalar<T>::type scalar;
+    typedef typename detail::sp_select_size_deleter<A, scalar,
+        detail::sp_array_count<T>::value>::type deleter;
+    shared_ptr<T> result(static_cast<type*>(0),
+        detail::sp_inplace_tag<deleter>(), allocator);
+    deleter* state = detail::sp_get_deleter<deleter>(result);
+    void* start = state->construct();
+    return shared_ptr<T>(result, static_cast<type*>(start));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared(const A& allocator,
+    const typename detail::sp_array_element<T>::type& value)
+{
+    typedef typename detail::sp_array_element<T>::type type;
+    typedef typename detail::sp_array_scalar<T>::type scalar;
+    typedef typename detail::sp_select_size_deleter<A, scalar,
+        detail::sp_array_count<T>::value>::type deleter;
+    shared_ptr<T> result(static_cast<type*>(0),
+        detail::sp_inplace_tag<deleter>(), allocator);
+    deleter* state = detail::sp_get_deleter<deleter>(result);
+    void* start = state->construct(reinterpret_cast<const
+        scalar*>(&value), detail::sp_array_count<type>::value);
+    return shared_ptr<T>(result, static_cast<type*>(start));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_size_array<T>::type
+allocate_shared_noinit(const A& allocator)
+{
+    typedef typename detail::sp_array_element<T>::type type;
+    typedef typename detail::sp_array_scalar<T>::type scalar;
+    typedef detail::sp_size_array_deleter<scalar,
+        detail::sp_array_count<T>::value> deleter;
+    shared_ptr<T> result(static_cast<type*>(0),
+        detail::sp_inplace_tag<deleter>(), allocator);
+    deleter* state = detail::sp_get_deleter<deleter>(result);
+    void* start = state->construct_default();
+    return shared_ptr<T>(result, static_cast<type*>(start));
 }
 
+template<class T, class A>
+inline typename detail::sp_if_array<T>::type
+allocate_shared(const A& allocator, std::size_t count)
+{
+    typedef typename detail::sp_array_element<T>::type type;
+    typedef typename detail::sp_array_scalar<T>::type scalar;
+    typedef typename detail::sp_select_deleter<A, scalar>::type deleter;
+    std::size_t size = count * detail::sp_array_count<type>::value;
+    void* start;
+    shared_ptr<T> result(static_cast<type*>(0),
+        detail::sp_inplace_tag<deleter>(),
+        detail::sp_array_allocator<scalar, A>(allocator, size, &start));
+    deleter* state = detail::sp_get_deleter<deleter>(result);
+    state->construct(static_cast<scalar*>(start));
+    return shared_ptr<T>(result, static_cast<type*>(start));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_array<T>::type
+allocate_shared(const A& allocator, std::size_t count,
+    const typename detail::sp_array_element<T>::type& value)
+{
+    typedef typename detail::sp_array_element<T>::type type;
+    typedef typename detail::sp_array_scalar<T>::type scalar;
+    typedef typename detail::sp_select_deleter<A, scalar>::type deleter;
+    std::size_t size = count * detail::sp_array_count<type>::value;
+    void* start;
+    shared_ptr<T> result(static_cast<type*>(0),
+        detail::sp_inplace_tag<deleter>(),
+        detail::sp_array_allocator<scalar, A>(allocator, size, &start));
+    deleter* state = detail::sp_get_deleter<deleter>(result);
+    state->construct(static_cast<scalar*>(start),
+        reinterpret_cast<const scalar*>(&value),
+        detail::sp_array_count<type>::value);
+    return shared_ptr<T>(result, static_cast<type*>(start));
+}
+
+template<class T, class A>
+inline typename detail::sp_if_array<T>::type
+allocate_shared_noinit(const A& allocator, std::size_t count)
+{
+    typedef typename detail::sp_array_element<T>::type type;
+    typedef typename detail::sp_array_scalar<T>::type scalar;
+    typedef detail::sp_array_deleter<scalar> deleter;
+    std::size_t size = count * detail::sp_array_count<type>::value;
+    void* start;
+    shared_ptr<T> result(static_cast<type*>(0),
+        detail::sp_inplace_tag<deleter>(),
+        detail::sp_array_allocator<scalar, A>(allocator, size, &start));
+    deleter* state = detail::sp_get_deleter<deleter>(result);
+    state->construct_default(static_cast<scalar*>(start));
+    return shared_ptr<T>(result, static_cast<type*>(start));
+}
+
+} /* boost */
+
 #endif