Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:08:50

0001 /*
0002 Copyright 2019-2021 Glen Joseph Fernandes
0003 (glenjofe@gmail.com)
0004 
0005 Distributed under the Boost Software License, Version 1.0.
0006 (http://www.boost.org/LICENSE_1_0.txt)
0007 */
0008 #ifndef BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
0009 #define BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
0010 
0011 #include <boost/core/allocator_access.hpp>
0012 #include <boost/core/alloc_construct.hpp>
0013 #include <boost/core/empty_value.hpp>
0014 #include <boost/core/first_scalar.hpp>
0015 #include <boost/core/noinit_adaptor.hpp>
0016 #include <boost/core/pointer_traits.hpp>
0017 #include <boost/smart_ptr/detail/sp_type_traits.hpp>
0018 #include <boost/config.hpp>
0019 #include <memory>
0020 #include <utility>
0021 #include <cstddef>
0022 #include <type_traits>
0023 
0024 namespace boost {
0025 namespace detail {
0026 
0027 template<class T>
0028 struct sp_alloc_size {
0029     static constexpr std::size_t value = 1;
0030 };
0031 
0032 template<class T>
0033 struct sp_alloc_size<T[]> {
0034     static constexpr std::size_t value = sp_alloc_size<T>::value;
0035 };
0036 
0037 template<class T, std::size_t N>
0038 struct sp_alloc_size<T[N]> {
0039     static constexpr std::size_t value = N * sp_alloc_size<T>::value;
0040 };
0041 
0042 template<class T>
0043 struct sp_alloc_result {
0044     typedef T type;
0045 };
0046 
0047 template<class T, std::size_t N>
0048 struct sp_alloc_result<T[N]> {
0049     typedef T type[];
0050 };
0051 
0052 template<class T>
0053 struct sp_alloc_value {
0054     typedef typename std::remove_cv<typename
0055         std::remove_extent<T>::type>::type type;
0056 };
0057 
0058 template<class T, class P>
0059 class sp_alloc_ptr {
0060 public:
0061     typedef T element_type;
0062 
0063     sp_alloc_ptr() noexcept
0064         : p_() { }
0065 
0066 #if defined(BOOST_MSVC) && BOOST_MSVC == 1600
0067     sp_alloc_ptr(T* p) noexcept
0068         : p_(const_cast<typename std::remove_cv<T>::type*>(p)) { }
0069 #endif
0070 
0071     sp_alloc_ptr(std::size_t, P p) noexcept
0072         : p_(p) { }
0073 
0074     sp_alloc_ptr(std::nullptr_t) noexcept
0075         : p_() { }
0076 
0077     T& operator*() const {
0078         return *p_;
0079     }
0080 
0081     T* operator->() const noexcept {
0082         return boost::to_address(p_);
0083     }
0084 
0085     explicit operator bool() const noexcept {
0086         return !!p_;
0087     }
0088 
0089     bool operator!() const noexcept {
0090         return !p_;
0091     }
0092 
0093     P ptr() const noexcept {
0094         return p_;
0095     }
0096 
0097     static constexpr std::size_t size() noexcept {
0098         return 1;
0099     }
0100 
0101 #if defined(BOOST_MSVC) && BOOST_MSVC < 1910
0102     static sp_alloc_ptr pointer_to(T& v) {
0103         return sp_alloc_ptr(1,
0104             std::pointer_traits<P>::pointer_to(const_cast<typename
0105                 std::remove_cv<T>::type&>(v)));
0106     }
0107 #endif
0108 
0109 private:
0110     P p_;
0111 };
0112 
0113 template<class T, class P>
0114 class sp_alloc_ptr<T[], P> {
0115 public:
0116     typedef T element_type;
0117 
0118     sp_alloc_ptr() noexcept
0119         : p_() { }
0120 
0121     sp_alloc_ptr(std::size_t n, P p) noexcept
0122         : p_(p)
0123         , n_(n) { }
0124 
0125     sp_alloc_ptr(std::nullptr_t) noexcept
0126         : p_() { }
0127 
0128     T& operator[](std::size_t i) const {
0129         return p_[i];
0130     }
0131 
0132     explicit operator bool() const noexcept {
0133         return !!p_;
0134     }
0135 
0136     bool operator!() const noexcept {
0137         return !p_;
0138     }
0139 
0140     P ptr() const noexcept {
0141         return p_;
0142     }
0143 
0144     std::size_t size() const noexcept {
0145         return n_;
0146     }
0147 
0148 #if defined(BOOST_MSVC) && BOOST_MSVC < 1910
0149     static sp_alloc_ptr pointer_to(T& v) {
0150         return sp_alloc_ptr(n_,
0151             std::pointer_traits<P>::pointer_to(const_cast<typename
0152                 std::remove_cv<T>::type&>(v)));
0153     }
0154 #endif
0155 
0156 private:
0157     P p_;
0158     std::size_t n_;
0159 };
0160 
0161 template<class T, std::size_t N, class P>
0162 class sp_alloc_ptr<T[N], P> {
0163 public:
0164     typedef T element_type;
0165 
0166     sp_alloc_ptr() noexcept
0167         : p_() { }
0168 
0169     sp_alloc_ptr(std::size_t, P p) noexcept
0170         : p_(p) { }
0171 
0172     sp_alloc_ptr(std::nullptr_t) noexcept
0173         : p_() { }
0174 
0175     T& operator[](std::size_t i) const {
0176         return p_[i];
0177     }
0178 
0179     explicit operator bool() const noexcept {
0180         return !!p_;
0181     }
0182 
0183     bool operator!() const noexcept {
0184         return !p_;
0185     }
0186 
0187     P ptr() const noexcept {
0188         return p_;
0189     }
0190 
0191     static constexpr std::size_t size() noexcept {
0192         return N;
0193     }
0194 
0195 #if defined(BOOST_MSVC) && BOOST_MSVC < 1910
0196     static sp_alloc_ptr pointer_to(T& v) {
0197         return sp_alloc_ptr(N,
0198             std::pointer_traits<P>::pointer_to(const_cast<typename
0199                 std::remove_cv<T>::type&>(v)));
0200     }
0201 #endif
0202 
0203 private:
0204     P p_;
0205 };
0206 
0207 template<class T, class P>
0208 inline bool
0209 operator==(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
0210 {
0211     return lhs.ptr() == rhs.ptr();
0212 }
0213 
0214 template<class T, class P>
0215 inline bool
0216 operator!=(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
0217 {
0218     return !(lhs == rhs);
0219 }
0220 
0221 template<class T, class P>
0222 inline bool
0223 operator==(const sp_alloc_ptr<T, P>& lhs,
0224     std::nullptr_t) noexcept
0225 {
0226     return !lhs.ptr();
0227 }
0228 
0229 template<class T, class P>
0230 inline bool
0231 operator==(std::nullptr_t,
0232     const sp_alloc_ptr<T, P>& rhs) noexcept
0233 {
0234     return !rhs.ptr();
0235 }
0236 
0237 template<class T, class P>
0238 inline bool
0239 operator!=(const sp_alloc_ptr<T, P>& lhs,
0240     std::nullptr_t) noexcept
0241 {
0242     return !!lhs.ptr();
0243 }
0244 
0245 template<class T, class P>
0246 inline bool
0247 operator!=(std::nullptr_t,
0248     const sp_alloc_ptr<T, P>& rhs) noexcept
0249 {
0250     return !!rhs.ptr();
0251 }
0252 
0253 template<class A>
0254 inline void
0255 sp_alloc_clear(A& a, typename boost::allocator_pointer<A>::type p, std::size_t,
0256     std::false_type)
0257 {
0258     boost::alloc_destroy(a, boost::to_address(p));
0259 }
0260 
0261 template<class A>
0262 inline void
0263 sp_alloc_clear(A& a, typename boost::allocator_pointer<A>::type p,
0264     std::size_t n, std::true_type)
0265 {
0266 #if defined(BOOST_MSVC) && BOOST_MSVC < 1800
0267     if (!p) {
0268         return;
0269     }
0270 #endif
0271     boost::alloc_destroy_n(a, boost::first_scalar(boost::to_address(p)),
0272         n * sp_alloc_size<typename A::value_type>::value);
0273 }
0274 
0275 } /* detail */
0276 
0277 template<class T, class A>
0278 class alloc_deleter
0279     : empty_value<typename allocator_rebind<A,
0280         typename detail::sp_alloc_value<T>::type>::type> {
0281     typedef typename allocator_rebind<A,
0282         typename detail::sp_alloc_value<T>::type>::type allocator;
0283     typedef empty_value<allocator> base;
0284 
0285 public:
0286     typedef detail::sp_alloc_ptr<T,
0287         typename allocator_pointer<allocator>::type> pointer;
0288 
0289     explicit alloc_deleter(const allocator& a) noexcept
0290         : base(empty_init_t(), a) { }
0291 
0292     void operator()(pointer p) {
0293         detail::sp_alloc_clear(base::get(), p.ptr(), p.size(), std::is_array<T>());
0294         base::get().deallocate(p.ptr(), p.size());
0295     }
0296 };
0297 
0298 template<class T, class A>
0299 using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A> >;
0300 
0301 namespace detail {
0302 
0303 template<class T, class A>
0304 class sp_alloc_make {
0305 public:
0306     typedef typename boost::allocator_rebind<A,
0307         typename sp_alloc_value<T>::type>::type allocator;
0308 
0309 private:
0310     typedef boost::alloc_deleter<T, A> deleter;
0311 
0312 public:
0313     typedef std::unique_ptr<typename sp_alloc_result<T>::type, deleter> type;
0314 
0315     sp_alloc_make(const A& a, std::size_t n)
0316         : a_(a)
0317         , n_(n)
0318         , p_(a_.allocate(n)) { }
0319 
0320     ~sp_alloc_make() {
0321         if (p_) {
0322             a_.deallocate(p_, n_);
0323         }
0324     }
0325 
0326     typename allocator::value_type* get() const noexcept {
0327         return boost::to_address(p_);
0328     }
0329 
0330     allocator& state() noexcept {
0331         return a_;
0332     }
0333 
0334     type release() noexcept {
0335         pointer p = p_;
0336         p_ = pointer();
0337         return type(typename deleter::pointer(n_, p), deleter(a_));
0338     }
0339 
0340 private:
0341     typedef typename boost::allocator_pointer<allocator>::type pointer;
0342 
0343     allocator a_;
0344     std::size_t n_;
0345     pointer p_;
0346 };
0347 
0348 } /* detail */
0349 
0350 template<class T, class A>
0351 inline typename std::enable_if<!std::is_array<T>::value,
0352     std::unique_ptr<T, alloc_deleter<T, A> > >::type
0353 allocate_unique(const A& alloc)
0354 {
0355     detail::sp_alloc_make<T, A> c(alloc, 1);
0356     boost::alloc_construct(c.state(), c.get());
0357     return c.release();
0358 }
0359 
0360 template<class T, class A, class... Args>
0361 inline typename std::enable_if<!std::is_array<T>::value,
0362     std::unique_ptr<T, alloc_deleter<T, A> > >::type
0363 allocate_unique(const A& alloc, Args&&... args)
0364 {
0365     detail::sp_alloc_make<T, A> c(alloc, 1);
0366     boost::alloc_construct(c.state(), c.get(), std::forward<Args>(args)...);
0367     return c.release();
0368 }
0369 
0370 template<class T, class A>
0371 inline typename std::enable_if<!std::is_array<T>::value,
0372     std::unique_ptr<T, alloc_deleter<T, A> > >::type
0373 allocate_unique(const A& alloc, typename detail::sp_type_identity<T>::type&& value)
0374 {
0375     detail::sp_alloc_make<T, A> c(alloc, 1);
0376     boost::alloc_construct(c.state(), c.get(), std::move(value));
0377     return c.release();
0378 }
0379 
0380 template<class T, class A>
0381 inline typename std::enable_if<!std::is_array<T>::value,
0382     std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
0383 allocate_unique_noinit(const A& alloc)
0384 {
0385     return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
0386 }
0387 
0388 template<class T, class A>
0389 inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value,
0390     std::unique_ptr<T, alloc_deleter<T, A> > >::type
0391 allocate_unique(const A& alloc, std::size_t size)
0392 {
0393     detail::sp_alloc_make<T, A> c(alloc, size);
0394     boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
0395         size * detail::sp_alloc_size<T>::value);
0396     return c.release();
0397 }
0398 
0399 template<class T, class A>
0400 inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
0401     std::unique_ptr<typename detail::sp_alloc_result<T>::type,
0402         alloc_deleter<T, A> > >::type
0403 allocate_unique(const A& alloc)
0404 {
0405     detail::sp_alloc_make<T, A> c(alloc, std::extent<T>::value);
0406     boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
0407         detail::sp_alloc_size<T>::value);
0408     return c.release();
0409 }
0410 
0411 template<class T, class A>
0412 inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value,
0413     std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
0414 allocate_unique_noinit(const A& alloc, std::size_t size)
0415 {
0416     return boost::allocate_unique<T, noinit_adaptor<A> >(alloc, size);
0417 }
0418 
0419 template<class T, class A>
0420 inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
0421     std::unique_ptr<typename detail::sp_alloc_result<T>::type,
0422         alloc_deleter<T, noinit_adaptor<A> > > >::type
0423 allocate_unique_noinit(const A& alloc)
0424 {
0425     return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
0426 }
0427 
0428 template<class T, class A>
0429 inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value,
0430     std::unique_ptr<T, alloc_deleter<T, A> > >::type
0431 allocate_unique(const A& alloc, std::size_t size,
0432     const typename std::remove_extent<T>::type& value)
0433 {
0434     detail::sp_alloc_make<T, A> c(alloc, size);
0435     boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
0436         size * detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
0437         detail::sp_alloc_size<typename std::remove_extent<T>::type>::value);
0438     return c.release();
0439 }
0440 
0441 template<class T, class A>
0442 inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
0443     std::unique_ptr<typename detail::sp_alloc_result<T>::type,
0444         alloc_deleter<T, A> > >::type
0445 allocate_unique(const A& alloc,
0446     const typename std::remove_extent<T>::type& value)
0447 {
0448     detail::sp_alloc_make<T, A> c(alloc, std::extent<T>::value);
0449     boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
0450         detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
0451         detail::sp_alloc_size<typename std::remove_extent<T>::type>::value);
0452     return c.release();
0453 }
0454 
0455 template<class T, class U, class A>
0456 inline typename allocator_pointer<typename allocator_rebind<A,
0457     typename detail::sp_alloc_value<T>::type>::type>::type
0458 get_allocator_pointer(const std::unique_ptr<T,
0459     alloc_deleter<U, A> >& p) noexcept
0460 {
0461     return p.get().ptr();
0462 }
0463 
0464 } /* boost */
0465 
0466 #endif