123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- /*
- 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/allocator_access.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;
- };
- template<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)));
- }
- #endif
- private:
- 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)));
- }
- #endif
- private:
- 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)));
- }
- #endif
- private:
- P p_;
- };
- template<class T, class P>
- inline bool
- operator==(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 bool
- operator!=(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 bool
- operator==(const sp_alloc_ptr<T, P>& lhs,
- detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
- {
- return !lhs.ptr();
- }
- template<class T, class P>
- inline bool
- operator==(detail::sp_nullptr_t,
- const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
- {
- return !rhs.ptr();
- }
- template<class T, class P>
- inline bool
- operator!=(const sp_alloc_ptr<T, P>& lhs,
- detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
- {
- return !!lhs.ptr();
- }
- template<class T, class P>
- inline bool
- operator!=(detail::sp_nullptr_t,
- const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
- {
- return !!rhs.ptr();
- }
- #endif
- template<class A>
- inline void
- sp_alloc_clear(A& a, typename boost::allocator_pointer<A>::type p, std::size_t,
- boost::false_type)
- {
- boost::alloc_destroy(a, boost::to_address(p));
- }
- template<class A>
- inline void
- sp_alloc_clear(A& a, typename boost::allocator_pointer<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 allocator_rebind<A,
- typename detail::sp_alloc_value<T>::type>::type> {
- typedef typename allocator_rebind<A,
- typename detail::sp_alloc_value<T>::type>::type allocator;
- typedef empty_value<allocator> base;
- public:
- typedef detail::sp_alloc_ptr<T,
- typename allocator_pointer<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> >;
- #endif
- namespace detail {
- template<class T, class A>
- class sp_alloc_make {
- public:
- typedef typename boost::allocator_rebind<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 boost::allocator_pointer<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> > >::type
- allocate_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> > >::type
- allocate_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();
- }
- #endif
- template<class T, class A>
- inline typename enable_if_<!is_array<T>::value,
- std::unique_ptr<T, alloc_deleter<T, A> > >::type
- allocate_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> > > >::type
- allocate_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> > >::type
- allocate_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> > >::type
- allocate_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> > > >::type
- allocate_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> > > >::type
- allocate_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> > >::type
- allocate_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> > >::type
- allocate_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
|