allocator_utilities.hpp 5.1 KB

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