123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- //////////////////////////////////////////////////////////////////////////////
- //
- // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // See http://www.boost.org/libs/container for documentation.
- //
- //////////////////////////////////////////////////////////////////////////////
- #ifndef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
- #define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
- #if defined (_MSC_VER)
- # pragma once
- #endif
- #include <boost/config.hpp>
- #include <boost/move/detail/type_traits.hpp>
- #include <boost/move/utility_core.hpp>
- #include <boost/container/detail/dispatch_uses_allocator.hpp>
- #include <boost/container/new_allocator.hpp>
- #include <boost/container/pmr/memory_resource.hpp>
- #include <boost/container/pmr/global_resource.hpp>
- #include <cstddef>
- namespace boost {
- namespace container {
- namespace pmr {
- //! A specialization of class template `polymorphic_allocator` conforms to the Allocator requirements.
- //! Constructed with different memory resources, different instances of the same specialization of
- //! `polymorphic_allocator` can exhibit entirely different allocation behavior. This runtime
- //! polymorphism allows objects that use polymorphic_allocator to behave as if they used different
- //! allocator types at run time even though they use the same static allocator type.
- template <class T>
- class polymorphic_allocator
- {
- public:
- typedef T value_type;
- //! <b>Effects</b>: Sets m_resource to
- //! `get_default_resource()`.
- polymorphic_allocator() BOOST_NOEXCEPT
- : m_resource(::boost::container::pmr::get_default_resource())
- {}
- //! <b>Requires</b>: r is non-null.
- //!
- //! <b>Effects</b>: Sets m_resource to r.
- //!
- //! <b>Throws</b>: Nothing
- //!
- //! <b>Notes</b>: This constructor provides an implicit conversion from memory_resource*.
- //! Non-standard extension: if r is null m_resource is set to get_default_resource().
- polymorphic_allocator(memory_resource* r)
- : m_resource(r ? r : ::boost::container::pmr::get_default_resource())
- {}
- //! <b>Effects</b>: Sets m_resource to
- //! other.resource().
- polymorphic_allocator(const polymorphic_allocator& other)
- : m_resource(other.m_resource)
- {}
- //! <b>Effects</b>: Sets m_resource to
- //! other.resource().
- template <class U>
- polymorphic_allocator(const polymorphic_allocator<U>& other) BOOST_NOEXCEPT
- : m_resource(other.resource())
- {}
- //! <b>Effects</b>: Sets m_resource to
- //! other.resource().
- polymorphic_allocator& operator=(const polymorphic_allocator& other)
- { m_resource = other.m_resource; return *this; }
- //! <b>Returns</b>: Equivalent to
- //! `static_cast<T*>(m_resource->allocate(n * sizeof(T), alignof(T)))`.
- T* allocate(size_t n)
- { return static_cast<T*>(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of<T>::value)); }
- //! <b>Requires</b>: p was allocated from a memory resource, x, equal to *m_resource,
- //! using `x.allocate(n * sizeof(T), alignof(T))`.
- //!
- //! <b>Effects</b>: Equivalent to m_resource->deallocate(p, n * sizeof(T), alignof(T)).
- //!
- //! <b>Throws</b>: Nothing.
- void deallocate(T* p, size_t n)
- { m_resource->deallocate(p, n*sizeof(T), ::boost::move_detail::alignment_of<T>::value); }
- #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //! <b>Requires</b>: Uses-allocator construction of T with allocator
- //! `*this` and constructor arguments `std::forward<Args>(args)...`
- //! is well-formed. [Note: uses-allocator construction is always well formed for
- //! types that do not use allocators. - end note]
- //!
- //! <b>Effects</b>: Construct a T object at p by uses-allocator construction with allocator
- //! `*this` and constructor arguments `std::forward<Args>(args)...`.
- //!
- //! <b>Throws</b>: Nothing unless the constructor for T throws.
- template < typename U, class ...Args>
- void construct(U* p, BOOST_FWD_REF(Args)...args)
- {
- new_allocator<U> na;
- dtl::dispatch_uses_allocator
- (na, *this, p, ::boost::forward<Args>(args)...);
- }
- #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //Disable this overload if the first argument is pair as some compilers have
- //overload selection problems when the first parameter is a pair.
- #define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE(N) \
- template < typename U BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
- void construct(U* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
- {\
- new_allocator<U> na;\
- dtl::dispatch_uses_allocator\
- (na, *this, p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
- }\
- //
- BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE)
- #undef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE
- #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //! <b>Effects</b>:
- //! p->~U().
- template <class U>
- void destroy(U* p)
- { (void)p; p->~U(); }
- //! <b>Returns</b>: Equivalent to
- //! `polymorphic_allocator()`.
- polymorphic_allocator select_on_container_copy_construction() const
- { return polymorphic_allocator(); }
- //! <b>Returns</b>:
- //! m_resource.
- memory_resource* resource() const
- { return m_resource; }
- private:
- memory_resource* m_resource;
- };
- //! <b>Returns</b>:
- //! `*a.resource() == *b.resource()`.
- template <class T1, class T2>
- bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
- { return *a.resource() == *b.resource(); }
- //! <b>Returns</b>:
- //! `! (a == b)`.
- template <class T1, class T2>
- bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
- { return *a.resource() != *b.resource(); }
- } //namespace pmr {
- } //namespace container {
- } //namespace boost {
- #endif //BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
|