allocator_utilities.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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/mpl/eval_if.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. typedef typename Allocator::BOOST_NESTED_TEMPLATE
  100. rebind<Type>::other other;
  101. };
  102. };
  103. template<typename Allocator,typename Type>
  104. struct compliant_allocator_rebind_to
  105. {
  106. typedef typename rebinder<Allocator>::
  107. BOOST_NESTED_TEMPLATE result<Type>::other type;
  108. };
  109. /* rebind front-end */
  110. template<typename Allocator,typename Type>
  111. struct rebind_to:
  112. mpl::eval_if_c<
  113. is_partial_std_allocator<Allocator>::value,
  114. partial_std_allocator_rebind_to<Allocator,Type>,
  115. compliant_allocator_rebind_to<Allocator,Type>
  116. >
  117. {
  118. };
  119. /* allocator-independent versions of construct and destroy */
  120. template<typename Type>
  121. void construct(void* p,const Type& t)
  122. {
  123. new (p) Type(t);
  124. }
  125. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  126. /* MSVC++ issues spurious warnings about unreferencend formal parameters
  127. * in destroy<Type> when Type is a class with trivial dtor.
  128. */
  129. #pragma warning(push)
  130. #pragma warning(disable:4100)
  131. #endif
  132. template<typename Type>
  133. void destroy(const Type* p)
  134. {
  135. #if BOOST_WORKAROUND(__SUNPRO_CC,BOOST_TESTED_AT(0x590))
  136. const_cast<Type*>(p)->~Type();
  137. #else
  138. p->~Type();
  139. #endif
  140. }
  141. #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
  142. #pragma warning(pop)
  143. #endif
  144. } /* namespace boost::detail::allocator */
  145. } /* namespace boost::detail */
  146. } /* namespace boost */
  147. #endif