diff options
Diffstat (limited to 'boost/container/pmr/polymorphic_allocator.hpp')
-rw-r--r-- | boost/container/pmr/polymorphic_allocator.hpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/boost/container/pmr/polymorphic_allocator.hpp b/boost/container/pmr/polymorphic_allocator.hpp new file mode 100644 index 0000000000..d189b3a311 --- /dev/null +++ b/boost/container/pmr/polymorphic_allocator.hpp @@ -0,0 +1,166 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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->resource()` 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->resource()` 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; + container_detail::dispatch_uses_allocator + (na, this->resource(), 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;\ + container_detail::dispatch_uses_allocator\ + (na, this->resource(), 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 |