| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 | /*Copyright 2019 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_UNIQUE_HPP#define BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP#include <boost/smart_ptr/detail/sp_noexcept.hpp>#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>#include <boost/core/alloc_construct.hpp>#include <boost/core/empty_value.hpp>#include <boost/core/first_scalar.hpp>#include <boost/core/noinit_adaptor.hpp>#include <boost/core/pointer_traits.hpp>#include <boost/type_traits/enable_if.hpp>#include <boost/type_traits/extent.hpp>#include <boost/type_traits/is_array.hpp>#include <boost/type_traits/is_bounded_array.hpp>#include <boost/type_traits/is_unbounded_array.hpp>#include <boost/type_traits/remove_cv.hpp>#include <boost/type_traits/remove_extent.hpp>#include <boost/type_traits/type_identity.hpp>#include <boost/config.hpp>#include <memory>#include <utility>namespace boost {namespace detail {template<class T>struct sp_alloc_size {    BOOST_STATIC_CONSTEXPR std::size_t value = 1;};template<class T>struct sp_alloc_size<T[]> {    BOOST_STATIC_CONSTEXPR std::size_t value = sp_alloc_size<T>::value;};template<class T, std::size_t N>struct sp_alloc_size<T[N]> {    BOOST_STATIC_CONSTEXPR std::size_t value = N * sp_alloc_size<T>::value;};template<class T>struct sp_alloc_result {    typedef T type;};template<class T, std::size_t N>struct sp_alloc_result<T[N]> {    typedef T type[];};template<class T>struct sp_alloc_value {    typedef typename boost::remove_cv<typename        boost::remove_extent<T>::type>::type type;};#if !defined(BOOST_NO_CXX11_ALLOCATOR)template<class A, class T>struct sp_alloc_to {    typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;};#elsetemplate<class A, class T>struct sp_alloc_to {    typedef typename A::template rebind<T>::other type;};#endif#if !defined(BOOST_NO_CXX11_ALLOCATOR)template<class A>struct sp_alloc_type {    typedef typename std::allocator_traits<A>::pointer type;};#elsetemplate<class A>struct sp_alloc_type {    typedef typename A::pointer type;};#endiftemplate<class T, class P>class sp_alloc_ptr {public:    typedef T element_type;    sp_alloc_ptr() BOOST_SP_NOEXCEPT        : p_() { }#if defined(BOOST_MSVC) && BOOST_MSVC == 1600    sp_alloc_ptr(T* p) BOOST_SP_NOEXCEPT        : p_(const_cast<typename boost::remove_cv<T>::type*>(p)) { }#endif    sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT        : p_(p) { }#if !defined(BOOST_NO_CXX11_NULLPTR)    sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT        : p_() { }#endif    T& operator*() const {        return *p_;    }    T* operator->() const BOOST_SP_NOEXCEPT {        return boost::to_address(p_);    }#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)    explicit operator bool() const BOOST_SP_NOEXCEPT {        return !!p_;    }#endif    bool operator!() const BOOST_SP_NOEXCEPT {        return !p_;    }    P ptr() const BOOST_SP_NOEXCEPT {        return p_;    }    BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {        return 1;    }#if defined(BOOST_MSVC) && BOOST_MSVC < 1910    static sp_alloc_ptr pointer_to(T& v) {        return sp_alloc_ptr(1,            std::pointer_traits<P>::pointer_to(const_cast<typename                boost::remove_cv<T>::type&>(v)));    }#endifprivate:    P p_;};template<class T, class P>class sp_alloc_ptr<T[], P> {public:    typedef T element_type;    sp_alloc_ptr() BOOST_SP_NOEXCEPT        : p_() { }    sp_alloc_ptr(std::size_t n, P p) BOOST_SP_NOEXCEPT        : p_(p)        , n_(n) { }#if !defined(BOOST_NO_CXX11_NULLPTR)    sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT        : p_() { }#endif    T& operator[](std::size_t i) const {        return p_[i];    }#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)    explicit operator bool() const BOOST_SP_NOEXCEPT {        return !!p_;    }#endif    bool operator!() const BOOST_SP_NOEXCEPT {        return !p_;    }    P ptr() const BOOST_SP_NOEXCEPT {        return p_;    }    std::size_t size() const BOOST_SP_NOEXCEPT {        return n_;    }#if defined(BOOST_MSVC) && BOOST_MSVC < 1910    static sp_alloc_ptr pointer_to(T& v) {        return sp_alloc_ptr(n_,            std::pointer_traits<P>::pointer_to(const_cast<typename                boost::remove_cv<T>::type&>(v)));    }#endifprivate:    P p_;    std::size_t n_;};template<class T, std::size_t N, class P>class sp_alloc_ptr<T[N], P> {public:    typedef T element_type;    sp_alloc_ptr() BOOST_SP_NOEXCEPT        : p_() { }    sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT        : p_(p) { }#if !defined(BOOST_NO_CXX11_NULLPTR)    sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT        : p_() { }#endif    T& operator[](std::size_t i) const {        return p_[i];    }#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)    explicit operator bool() const BOOST_SP_NOEXCEPT {        return !!p_;    }#endif    bool operator!() const BOOST_SP_NOEXCEPT {        return !p_;    }    P ptr() const BOOST_SP_NOEXCEPT {        return p_;    }    BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {        return N;    }#if defined(BOOST_MSVC) && BOOST_MSVC < 1910    static sp_alloc_ptr pointer_to(T& v) {        return sp_alloc_ptr(N,            std::pointer_traits<P>::pointer_to(const_cast<typename                boost::remove_cv<T>::type&>(v)));    }#endifprivate:    P p_;};template<class T, class P>inline booloperator==(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs){    return lhs.ptr() == rhs.ptr();}template<class T, class P>inline booloperator!=(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs){    return !(lhs == rhs);}#if !defined(BOOST_NO_CXX11_NULLPTR)template<class T, class P>inline booloperator==(const sp_alloc_ptr<T, P>& lhs,    detail::sp_nullptr_t) BOOST_SP_NOEXCEPT{    return !lhs.ptr();}template<class T, class P>inline booloperator==(detail::sp_nullptr_t,    const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT{    return !rhs.ptr();}template<class T, class P>inline booloperator!=(const sp_alloc_ptr<T, P>& lhs,    detail::sp_nullptr_t) BOOST_SP_NOEXCEPT{    return !!lhs.ptr();}template<class T, class P>inline booloperator!=(detail::sp_nullptr_t,    const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT{    return !!rhs.ptr();}#endiftemplate<class A>inline voidsp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t,    boost::false_type){    boost::alloc_destroy(a, boost::to_address(p));}template<class A>inline voidsp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t n,    boost::true_type){#if defined(BOOST_MSVC) && BOOST_MSVC < 1800    if (!p) {        return;    }#endif    boost::alloc_destroy_n(a, boost::first_scalar(boost::to_address(p)),        n * sp_alloc_size<typename A::value_type>::value);}} /* detail */template<class T, class A>class alloc_deleter    : empty_value<typename detail::sp_alloc_to<A,        typename detail::sp_alloc_value<T>::type>::type> {    typedef typename detail::sp_alloc_to<A,        typename detail::sp_alloc_value<T>::type>::type allocator;    typedef empty_value<allocator> base;public:    typedef detail::sp_alloc_ptr<T,        typename detail::sp_alloc_type<allocator>::type> pointer;    explicit alloc_deleter(const allocator& a) BOOST_SP_NOEXCEPT        : base(empty_init_t(), a) { }    void operator()(pointer p) {        detail::sp_alloc_clear(base::get(), p.ptr(), p.size(), is_array<T>());        base::get().deallocate(p.ptr(), p.size());    }};#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)template<class T, class A>using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A> >;#endifnamespace detail {template<class T, class A>class sp_alloc_make {public:    typedef typename sp_alloc_to<A,        typename sp_alloc_value<T>::type>::type allocator;private:    typedef boost::alloc_deleter<T, A> deleter;public:    typedef std::unique_ptr<typename sp_alloc_result<T>::type, deleter> type;    sp_alloc_make(const A& a, std::size_t n)        : a_(a)        , n_(n)        , p_(a_.allocate(n)) { }    ~sp_alloc_make() {        if (p_) {            a_.deallocate(p_, n_);        }    }    typename allocator::value_type* get() const BOOST_SP_NOEXCEPT {        return boost::to_address(p_);    }    allocator& state() BOOST_SP_NOEXCEPT {        return a_;    }    type release() BOOST_SP_NOEXCEPT {        pointer p = p_;        p_ = pointer();        return type(typename deleter::pointer(n_, p), deleter(a_));    }private:    typedef typename sp_alloc_type<allocator>::type pointer;    allocator a_;    std::size_t n_;    pointer p_;};} /* detail */template<class T, class A>inline typename enable_if_<!is_array<T>::value,    std::unique_ptr<T, alloc_deleter<T, A> > >::typeallocate_unique(const A& alloc){    detail::sp_alloc_make<T, A> c(alloc, 1);    boost::alloc_construct(c.state(), c.get());    return c.release();}#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)template<class T, class A, class... Args>inline typename enable_if_<!is_array<T>::value,    std::unique_ptr<T, alloc_deleter<T, A> > >::typeallocate_unique(const A& alloc, Args&&... args){    detail::sp_alloc_make<T, A> c(alloc, 1);    boost::alloc_construct(c.state(), c.get(), std::forward<Args>(args)...);    return c.release();}#endiftemplate<class T, class A>inline typename enable_if_<!is_array<T>::value,    std::unique_ptr<T, alloc_deleter<T, A> > >::typeallocate_unique(const A& alloc, typename type_identity<T>::type&& value){    detail::sp_alloc_make<T, A> c(alloc, 1);    boost::alloc_construct(c.state(), c.get(), std::move(value));    return c.release();}template<class T, class A>inline typename enable_if_<!is_array<T>::value,    std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::typeallocate_unique_noinit(const A& alloc){    return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);}template<class T, class A>inline typename enable_if_<is_unbounded_array<T>::value,    std::unique_ptr<T, alloc_deleter<T, A> > >::typeallocate_unique(const A& alloc, std::size_t size){    detail::sp_alloc_make<T, A> c(alloc, size);    boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),        size * detail::sp_alloc_size<T>::value);    return c.release();}template<class T, class A>inline typename enable_if_<is_bounded_array<T>::value,    std::unique_ptr<typename detail::sp_alloc_result<T>::type,        alloc_deleter<T, A> > >::typeallocate_unique(const A& alloc){    detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);    boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),        detail::sp_alloc_size<T>::value);    return c.release();}template<class T, class A>inline typename enable_if_<is_unbounded_array<T>::value,    std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::typeallocate_unique_noinit(const A& alloc, std::size_t size){    return boost::allocate_unique<T, noinit_adaptor<A> >(alloc, size);}template<class T, class A>inline typename enable_if_<is_bounded_array<T>::value,    std::unique_ptr<typename detail::sp_alloc_result<T>::type,        alloc_deleter<T, noinit_adaptor<A> > > >::typeallocate_unique_noinit(const A& alloc){    return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);}template<class T, class A>inline typename enable_if_<is_unbounded_array<T>::value,    std::unique_ptr<T, alloc_deleter<T, A> > >::typeallocate_unique(const A& alloc, std::size_t size,    const typename remove_extent<T>::type& value){    detail::sp_alloc_make<T, A> c(alloc, size);    boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),        size * detail::sp_alloc_size<T>::value, boost::first_scalar(&value),        detail::sp_alloc_size<typename remove_extent<T>::type>::value);    return c.release();}template<class T, class A>inline typename enable_if_<is_bounded_array<T>::value,    std::unique_ptr<typename detail::sp_alloc_result<T>::type,        alloc_deleter<T, A> > >::typeallocate_unique(const A& alloc,    const typename remove_extent<T>::type& value){    detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);    boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),        detail::sp_alloc_size<T>::value, boost::first_scalar(&value),        detail::sp_alloc_size<typename remove_extent<T>::type>::value);    return c.release();}} /* boost */#endif
 |