allocator_utilities.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /* Copyright 2003-2013 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 Boost website at http://www.boost.org/
  7. */
  8. #ifndef BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP
  9. #define BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP
  10. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  11. #include <boost/detail/workaround.hpp>
  12. #include <boost/detail/select_type.hpp>
  13. #include <boost/type_traits/is_same.hpp>
  14. #include <cstddef>
  15. #include <memory>
  16. #include <new>
  17. namespace boost{
  18. namespace detail{
  19. /* Allocator adaption layer. Some stdlibs provide allocators without rebind
  20. * and template ctors. These facilities are simulated with the external
  21. * template class rebind_to and the aid of partial_std_allocator_wrapper.
  22. */
  23. namespace allocator{
  24. /* partial_std_allocator_wrapper inherits the functionality of a std
  25. * allocator while providing a templatized ctor and other bits missing
  26. * in some stdlib implementation or another.
  27. */
  28. template<typename Type>
  29. class partial_std_allocator_wrapper:public std::allocator<Type>
  30. {
  31. public:
  32. /* Oddly enough, STLport does not define std::allocator<void>::value_type
  33. * when configured to work without partial template specialization.
  34. * No harm in supplying the definition here unconditionally.
  35. */
  36. typedef Type value_type;
  37. partial_std_allocator_wrapper(){}
  38. template<typename Other>
  39. partial_std_allocator_wrapper(const partial_std_allocator_wrapper<Other>&){}
  40. partial_std_allocator_wrapper(const std::allocator<Type>& x):
  41. std::allocator<Type>(x)
  42. {
  43. }
  44. #if defined(BOOST_DINKUMWARE_STDLIB)
  45. /* Dinkumware guys didn't provide a means to call allocate() without
  46. * supplying a hint, in disagreement with the standard.
  47. */
  48. Type* allocate(std::size_t n,const void* hint=0)
  49. {
  50. std::allocator<Type>& a=*this;
  51. return a.allocate(n,hint);
  52. }
  53. #endif
  54. };
  55. /* Detects whether a given allocator belongs to a defective stdlib not
  56. * having the required member templates.
  57. * Note that it does not suffice to check the Boost.Config stdlib
  58. * macros, as the user might have passed a custom, compliant allocator.
  59. * The checks also considers partial_std_allocator_wrapper to be
  60. * a standard defective allocator.
  61. */
  62. #if defined(BOOST_NO_STD_ALLOCATOR)&&\
  63. (defined(BOOST_HAS_PARTIAL_STD_ALLOCATOR)||defined(BOOST_DINKUMWARE_STDLIB))
  64. template<typename Allocator>
  65. struct is_partial_std_allocator
  66. {
  67. BOOST_STATIC_CONSTANT(bool,
  68. value=
  69. (is_same<
  70. std::allocator<BOOST_DEDUCED_TYPENAME Allocator::value_type>,
  71. Allocator
  72. >::value)||
  73. (is_same<
  74. partial_std_allocator_wrapper<
  75. BOOST_DEDUCED_TYPENAME Allocator::value_type>,
  76. Allocator
  77. >::value));
  78. };
  79. #else
  80. template<typename Allocator>
  81. struct is_partial_std_allocator
  82. {
  83. BOOST_STATIC_CONSTANT(bool,value=false);
  84. };
  85. #endif
  86. /* rebind operations for defective std allocators */
  87. template<typename Allocator,typename Type>
  88. struct partial_std_allocator_rebind_to
  89. {
  90. typedef partial_std_allocator_wrapper<Type> type;
  91. };
  92. /* rebind operation in all other cases */
  93. template<typename Allocator>
  94. struct rebinder
  95. {
  96. template<typename Type>
  97. struct result
  98. {
  99. #ifdef BOOST_NO_CXX11_ALLOCATOR
  100. typedef typename Allocator::BOOST_NESTED_TEMPLATE
  101. rebind<Type>::other other;
  102. #else
  103. typedef typename std::allocator_traits<Allocator>::BOOST_NESTED_TEMPLATE
  104. rebind_alloc<Type> other;
  105. #endif
  106. };
  107. };
  108. template<typename Allocator,typename Type>
  109. struct compliant_allocator_rebind_to
  110. {
  111. typedef typename rebinder<Allocator>::
  112. BOOST_NESTED_TEMPLATE result<Type>::other type;
  113. };
  114. /* rebind front-end */
  115. template<typename Allocator,typename Type>
  116. struct rebind_to:
  117. boost::detail::if_true<
  118. is_partial_std_allocator<Allocator>::value
  119. >::template then<
  120. partial_std_allocator_rebind_to<Allocator,Type>,
  121. compliant_allocator_rebind_to<Allocator,Type>
  122. >::type
  123. {
  124. };
  125. /* allocator-independent versions of construct and destroy */
  126. template<typename Type>
  127. void construct(void* p,const Type& t)
  128. {
  129. new (p) Type(t);
  130. }
  131. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  132. /* MSVC++ issues spurious warnings about unreferencend formal parameters
  133. * in destroy<Type> when Type is a class with trivial dtor.
  134. */
  135. #pragma warning(push)
  136. #pragma warning(disable:4100)
  137. #endif
  138. template<typename Type>
  139. void destroy(const Type* p)
  140. {
  141. #if BOOST_WORKAROUND(__SUNPRO_CC,BOOST_TESTED_AT(0x590))
  142. const_cast<Type*>(p)->~Type();
  143. #else
  144. p->~Type();
  145. #endif
  146. }
  147. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  148. #pragma warning(pop)
  149. #endif
  150. } /* namespace boost::detail::allocator */
  151. } /* namespace boost::detail */
  152. } /* namespace boost */
  153. #endif