allocator_traits.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* Copyright 2003-2020 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_DETAIL_ALLOCATOR_TRAITS_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_ALLOCATOR_TRAITS_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #if !defined(BOOST_NO_CXX11_ALLOCATOR)
  15. #include <boost/type_traits/is_empty.hpp>
  16. #include <memory>
  17. #else
  18. #include <boost/detail/workaround.hpp>
  19. #include <boost/move/core.hpp>
  20. #include <boost/move/utility_core.hpp>
  21. #include <boost/multi_index/detail/vartempl_support.hpp>
  22. #include <boost/type_traits/integral_constant.hpp>
  23. #include <boost/type_traits/is_empty.hpp>
  24. #include <new>
  25. #endif
  26. namespace boost{
  27. namespace multi_index{
  28. namespace detail{
  29. /* poor man's replacement of std::allocator_traits */
  30. #if !defined(BOOST_NO_CXX11_ALLOCATOR)
  31. template<typename T> struct void_helper{typedef void type;};
  32. template<typename Allocator,typename=void>
  33. struct allocator_is_always_equal:boost::is_empty<Allocator>{};
  34. template<typename Allocator>
  35. struct allocator_is_always_equal<
  36. Allocator,
  37. typename void_helper<
  38. typename std::allocator_traits<Allocator>::is_always_equal
  39. >::type
  40. >:std::allocator_traits<Allocator>::is_always_equal{};
  41. template<typename Allocator>
  42. struct allocator_traits:std::allocator_traits<Allocator>
  43. {
  44. /* wrap std::allocator_traits alias templates for use in C++03 codebase */
  45. typedef std::allocator_traits<Allocator> super;
  46. /* pre-C++17 compatibilty */
  47. typedef allocator_is_always_equal<Allocator> is_always_equal;
  48. template<typename T>
  49. struct rebind_alloc
  50. {
  51. typedef typename super::template rebind_alloc<T> type;
  52. };
  53. template<typename T>
  54. struct rebind_traits
  55. {
  56. typedef typename super::template rebind_traits<T> type;
  57. };
  58. };
  59. #else
  60. /* not a full std::allocator_traits rewrite (not needed) */
  61. template<typename Allocator>
  62. struct allocator_traits
  63. {
  64. typedef Allocator allocator_type;
  65. typedef typename Allocator::value_type value_type;
  66. typedef typename Allocator::pointer pointer;
  67. typedef typename Allocator::const_pointer const_pointer;
  68. /* [const_]void_pointer not provided as boost::pointer_traits's
  69. * rebind_to has been seen to fail with things like
  70. * boost::interprocess::offset_ptr in relatively old environments.
  71. */
  72. typedef typename Allocator::difference_type difference_type;
  73. typedef typename Allocator::size_type size_type;
  74. typedef boost::false_type propagate_on_container_copy_assignment;
  75. typedef boost::false_type propagate_on_container_move_assignment;
  76. typedef boost::false_type propagate_on_container_swap;
  77. typedef boost::is_empty<Allocator> is_always_equal;
  78. template<typename T>
  79. struct rebind_alloc
  80. {
  81. typedef typename Allocator::template rebind<T>::other type;
  82. };
  83. template<typename T>
  84. struct rebind_traits
  85. {
  86. typedef allocator_traits<typename rebind_alloc<T>::type> type;
  87. };
  88. static pointer allocate(Allocator& a,size_type n){return a.allocate(n);}
  89. static pointer allocate(Allocator& a,size_type n,const_pointer p)
  90. /* should've been const_void_pointer p */
  91. {return a.allocate(n,p);}
  92. static void deallocate(Allocator& a,pointer p,size_type n)
  93. {a.deallocate(p,n);}
  94. template<typename T>
  95. static void construct(Allocator&,T* p,const T& x)
  96. {::new (static_cast<void*>(p)) T(x);}
  97. template<typename T>
  98. static void construct(Allocator&,T* p,BOOST_RV_REF(T) x)
  99. {::new (static_cast<void*>(p)) T(boost::move(x));}
  100. template<typename T,BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  101. static void construct(Allocator&,T* p,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  102. {
  103. vartempl_placement_new(p,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  104. }
  105. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  106. /* MSVC issues spurious warnings about unreferencend formal parameters in
  107. * destroy<T> when T is a class with trivial dtor.
  108. */
  109. #pragma warning(push)
  110. #pragma warning(disable:4100)
  111. #endif
  112. template<typename T>
  113. static void destroy(Allocator&,T* p){p->~T();}
  114. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  115. #pragma warning(pop)
  116. #endif
  117. static size_type max_size(Allocator& a)BOOST_NOEXCEPT{return a.max_size();}
  118. static Allocator select_on_container_copy_construction(const Allocator& a)
  119. {
  120. return a;
  121. }
  122. };
  123. #endif
  124. template<typename Allocator,typename T>
  125. struct rebind_alloc_for
  126. {
  127. typedef typename allocator_traits<Allocator>::
  128. template rebind_alloc<T>::type type;
  129. };
  130. } /* namespace multi_index::detail */
  131. } /* namespace multi_index */
  132. } /* namespace boost */
  133. #endif