polymorphic_allocator.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
  11. #define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
  12. #if defined (_MSC_VER)
  13. # pragma once
  14. #endif
  15. #include <boost/config.hpp>
  16. #include <boost/move/detail/type_traits.hpp>
  17. #include <boost/move/utility_core.hpp>
  18. #include <boost/container/detail/dispatch_uses_allocator.hpp>
  19. #include <boost/container/new_allocator.hpp>
  20. #include <boost/container/pmr/memory_resource.hpp>
  21. #include <boost/container/pmr/global_resource.hpp>
  22. #include <cstddef>
  23. namespace boost {
  24. namespace container {
  25. namespace pmr {
  26. //! A specialization of class template `polymorphic_allocator` conforms to the Allocator requirements.
  27. //! Constructed with different memory resources, different instances of the same specialization of
  28. //! `polymorphic_allocator` can exhibit entirely different allocation behavior. This runtime
  29. //! polymorphism allows objects that use polymorphic_allocator to behave as if they used different
  30. //! allocator types at run time even though they use the same static allocator type.
  31. template <class T>
  32. class polymorphic_allocator
  33. {
  34. public:
  35. typedef T value_type;
  36. //! <b>Effects</b>: Sets m_resource to
  37. //! `get_default_resource()`.
  38. polymorphic_allocator() BOOST_NOEXCEPT
  39. : m_resource(::boost::container::pmr::get_default_resource())
  40. {}
  41. //! <b>Requires</b>: r is non-null.
  42. //!
  43. //! <b>Effects</b>: Sets m_resource to r.
  44. //!
  45. //! <b>Throws</b>: Nothing
  46. //!
  47. //! <b>Notes</b>: This constructor provides an implicit conversion from memory_resource*.
  48. //! Non-standard extension: if r is null m_resource is set to get_default_resource().
  49. polymorphic_allocator(memory_resource* r)
  50. : m_resource(r ? r : ::boost::container::pmr::get_default_resource())
  51. {}
  52. //! <b>Effects</b>: Sets m_resource to
  53. //! other.resource().
  54. polymorphic_allocator(const polymorphic_allocator& other)
  55. : m_resource(other.m_resource)
  56. {}
  57. //! <b>Effects</b>: Sets m_resource to
  58. //! other.resource().
  59. template <class U>
  60. polymorphic_allocator(const polymorphic_allocator<U>& other) BOOST_NOEXCEPT
  61. : m_resource(other.resource())
  62. {}
  63. //! <b>Effects</b>: Sets m_resource to
  64. //! other.resource().
  65. polymorphic_allocator& operator=(const polymorphic_allocator& other)
  66. { m_resource = other.m_resource; return *this; }
  67. //! <b>Returns</b>: Equivalent to
  68. //! `static_cast<T*>(m_resource->allocate(n * sizeof(T), alignof(T)))`.
  69. T* allocate(size_t n)
  70. { return static_cast<T*>(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of<T>::value)); }
  71. //! <b>Requires</b>: p was allocated from a memory resource, x, equal to *m_resource,
  72. //! using `x.allocate(n * sizeof(T), alignof(T))`.
  73. //!
  74. //! <b>Effects</b>: Equivalent to m_resource->deallocate(p, n * sizeof(T), alignof(T)).
  75. //!
  76. //! <b>Throws</b>: Nothing.
  77. void deallocate(T* p, size_t n)
  78. { m_resource->deallocate(p, n*sizeof(T), ::boost::move_detail::alignment_of<T>::value); }
  79. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  80. //! <b>Requires</b>: Uses-allocator construction of T with allocator
  81. //! `*this` and constructor arguments `std::forward<Args>(args)...`
  82. //! is well-formed. [Note: uses-allocator construction is always well formed for
  83. //! types that do not use allocators. - end note]
  84. //!
  85. //! <b>Effects</b>: Construct a T object at p by uses-allocator construction with allocator
  86. //! `*this` and constructor arguments `std::forward<Args>(args)...`.
  87. //!
  88. //! <b>Throws</b>: Nothing unless the constructor for T throws.
  89. template < typename U, class ...Args>
  90. void construct(U* p, BOOST_FWD_REF(Args)...args)
  91. {
  92. new_allocator<U> na;
  93. dtl::dispatch_uses_allocator
  94. (na, *this, p, ::boost::forward<Args>(args)...);
  95. }
  96. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  97. //Disable this overload if the first argument is pair as some compilers have
  98. //overload selection problems when the first parameter is a pair.
  99. #define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE(N) \
  100. template < typename U BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
  101. void construct(U* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
  102. {\
  103. new_allocator<U> na;\
  104. dtl::dispatch_uses_allocator\
  105. (na, *this, p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
  106. }\
  107. //
  108. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE)
  109. #undef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE
  110. #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  111. //! <b>Effects</b>:
  112. //! p->~U().
  113. template <class U>
  114. void destroy(U* p)
  115. { (void)p; p->~U(); }
  116. //! <b>Returns</b>: Equivalent to
  117. //! `polymorphic_allocator()`.
  118. polymorphic_allocator select_on_container_copy_construction() const
  119. { return polymorphic_allocator(); }
  120. //! <b>Returns</b>:
  121. //! m_resource.
  122. memory_resource* resource() const
  123. { return m_resource; }
  124. private:
  125. memory_resource* m_resource;
  126. };
  127. //! <b>Returns</b>:
  128. //! `*a.resource() == *b.resource()`.
  129. template <class T1, class T2>
  130. bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
  131. { return *a.resource() == *b.resource(); }
  132. //! <b>Returns</b>:
  133. //! `! (a == b)`.
  134. template <class T1, class T2>
  135. bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
  136. { return *a.resource() != *b.resource(); }
  137. } //namespace pmr {
  138. } //namespace container {
  139. } //namespace boost {
  140. #endif //BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP