////////////////////////////////////////////////////////////////////////////// // // (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 #include #include #include #include #include #include #include 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 polymorphic_allocator { public: typedef T value_type; //! Effects: Sets m_resource to //! `get_default_resource()`. polymorphic_allocator() BOOST_NOEXCEPT : m_resource(::boost::container::pmr::get_default_resource()) {} //! Requires: r is non-null. //! //! Effects: Sets m_resource to r. //! //! Throws: Nothing //! //! Notes: 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()) {} //! Effects: Sets m_resource to //! other.resource(). polymorphic_allocator(const polymorphic_allocator& other) : m_resource(other.m_resource) {} //! Effects: Sets m_resource to //! other.resource(). template polymorphic_allocator(const polymorphic_allocator& other) BOOST_NOEXCEPT : m_resource(other.resource()) {} //! Effects: Sets m_resource to //! other.resource(). polymorphic_allocator& operator=(const polymorphic_allocator& other) { m_resource = other.m_resource; return *this; } //! Returns: Equivalent to //! `static_cast(m_resource->allocate(n * sizeof(T), alignof(T)))`. T* allocate(size_t n) { return static_cast(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of::value)); } //! Requires: p was allocated from a memory resource, x, equal to *m_resource, //! using `x.allocate(n * sizeof(T), alignof(T))`. //! //! Effects: Equivalent to m_resource->deallocate(p, n * sizeof(T), alignof(T)). //! //! Throws: Nothing. void deallocate(T* p, size_t n) { m_resource->deallocate(p, n*sizeof(T), ::boost::move_detail::alignment_of::value); } #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! Requires: Uses-allocator construction of T with allocator //! `*this` and constructor arguments `std::forward(args)...` //! is well-formed. [Note: uses-allocator construction is always well formed for //! types that do not use allocators. - end note] //! //! Effects: Construct a T object at p by uses-allocator construction with allocator //! `*this` and constructor arguments `std::forward(args)...`. //! //! Throws: Nothing unless the constructor for T throws. template < typename U, class ...Args> void construct(U* p, BOOST_FWD_REF(Args)...args) { new_allocator na; dtl::dispatch_uses_allocator (na, *this, p, ::boost::forward(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 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) //! Effects: //! p->~U(). template void destroy(U* p) { (void)p; p->~U(); } //! Returns: Equivalent to //! `polymorphic_allocator()`. polymorphic_allocator select_on_container_copy_construction() const { return polymorphic_allocator(); } //! Returns: //! m_resource. memory_resource* resource() const { return m_resource; } private: memory_resource* m_resource; }; //! Returns: //! `*a.resource() == *b.resource()`. template bool operator==(const polymorphic_allocator& a, const polymorphic_allocator& b) BOOST_NOEXCEPT { return *a.resource() == *b.resource(); } //! Returns: //! `! (a == b)`. template bool operator!=(const polymorphic_allocator& a, const polymorphic_allocator& b) BOOST_NOEXCEPT { return *a.resource() != *b.resource(); } } //namespace pmr { } //namespace container { } //namespace boost { #endif //BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP