EVOLUTION-MANAGER
Edit File: polymorphic_allocator.hpp
////////////////////////////////////////////////////////////////////////////// // // (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