associated_allocator.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. //
  2. // associated_allocator.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP
  11. #define BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <memory>
  17. #include <boost/asio/associator.hpp>
  18. #include <boost/asio/detail/functional.hpp>
  19. #include <boost/asio/detail/type_traits.hpp>
  20. #include <boost/asio/detail/push_options.hpp>
  21. namespace boost {
  22. namespace asio {
  23. template <typename T, typename Allocator>
  24. struct associated_allocator;
  25. namespace detail {
  26. template <typename T, typename = void>
  27. struct has_allocator_type : false_type
  28. {
  29. };
  30. template <typename T>
  31. struct has_allocator_type<T,
  32. typename void_type<typename T::allocator_type>::type>
  33. : true_type
  34. {
  35. };
  36. template <typename T, typename A, typename = void, typename = void>
  37. struct associated_allocator_impl
  38. {
  39. typedef void asio_associated_allocator_is_unspecialised;
  40. typedef A type;
  41. static type get(const T&) BOOST_ASIO_NOEXCEPT
  42. {
  43. return type();
  44. }
  45. static const type& get(const T&, const A& a) BOOST_ASIO_NOEXCEPT
  46. {
  47. return a;
  48. }
  49. };
  50. template <typename T, typename A>
  51. struct associated_allocator_impl<T, A,
  52. typename void_type<typename T::allocator_type>::type>
  53. {
  54. typedef typename T::allocator_type type;
  55. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(
  56. const T& t) BOOST_ASIO_NOEXCEPT
  57. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_allocator()))
  58. {
  59. return t.get_allocator();
  60. }
  61. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(
  62. const T& t, const A&) BOOST_ASIO_NOEXCEPT
  63. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_allocator()))
  64. {
  65. return t.get_allocator();
  66. }
  67. };
  68. template <typename T, typename A>
  69. struct associated_allocator_impl<T, A,
  70. typename enable_if<
  71. !has_allocator_type<T>::value
  72. >::type,
  73. typename void_type<
  74. typename associator<associated_allocator, T, A>::type
  75. >::type> : associator<associated_allocator, T, A>
  76. {
  77. };
  78. } // namespace detail
  79. /// Traits type used to obtain the allocator associated with an object.
  80. /**
  81. * A program may specialise this traits type if the @c T template parameter in
  82. * the specialisation is a user-defined type. The template parameter @c
  83. * Allocator shall be a type meeting the Allocator requirements.
  84. *
  85. * Specialisations shall meet the following requirements, where @c t is a const
  86. * reference to an object of type @c T, and @c a is an object of type @c
  87. * Allocator.
  88. *
  89. * @li Provide a nested typedef @c type that identifies a type meeting the
  90. * Allocator requirements.
  91. *
  92. * @li Provide a noexcept static member function named @c get, callable as @c
  93. * get(t) and with return type @c type or a (possibly const) reference to @c
  94. * type.
  95. *
  96. * @li Provide a noexcept static member function named @c get, callable as @c
  97. * get(t,a) and with return type @c type or a (possibly const) reference to @c
  98. * type.
  99. */
  100. template <typename T, typename Allocator = std::allocator<void> >
  101. struct associated_allocator
  102. #if !defined(GENERATING_DOCUMENTATION)
  103. : detail::associated_allocator_impl<T, Allocator>
  104. #endif // !defined(GENERATING_DOCUMENTATION)
  105. {
  106. #if defined(GENERATING_DOCUMENTATION)
  107. /// If @c T has a nested type @c allocator_type, <tt>T::allocator_type</tt>.
  108. /// Otherwise @c Allocator.
  109. typedef see_below type;
  110. /// If @c T has a nested type @c allocator_type, returns
  111. /// <tt>t.get_allocator()</tt>. Otherwise returns @c type().
  112. static decltype(auto) get(const T& t) BOOST_ASIO_NOEXCEPT;
  113. /// If @c T has a nested type @c allocator_type, returns
  114. /// <tt>t.get_allocator()</tt>. Otherwise returns @c a.
  115. static decltype(auto) get(const T& t, const Allocator& a) BOOST_ASIO_NOEXCEPT;
  116. #endif // defined(GENERATING_DOCUMENTATION)
  117. };
  118. /// Helper function to obtain an object's associated allocator.
  119. /**
  120. * @returns <tt>associated_allocator<T>::get(t)</tt>
  121. */
  122. template <typename T>
  123. BOOST_ASIO_NODISCARD inline typename associated_allocator<T>::type
  124. get_associated_allocator(const T& t) BOOST_ASIO_NOEXCEPT
  125. {
  126. return associated_allocator<T>::get(t);
  127. }
  128. /// Helper function to obtain an object's associated allocator.
  129. /**
  130. * @returns <tt>associated_allocator<T, Allocator>::get(t, a)</tt>
  131. */
  132. template <typename T, typename Allocator>
  133. BOOST_ASIO_NODISCARD inline BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  134. typename associated_allocator<T, Allocator>::type)
  135. get_associated_allocator(const T& t, const Allocator& a) BOOST_ASIO_NOEXCEPT
  136. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  137. associated_allocator<T, Allocator>::get(t, a)))
  138. {
  139. return associated_allocator<T, Allocator>::get(t, a);
  140. }
  141. #if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
  142. template <typename T, typename Allocator = std::allocator<void> >
  143. using associated_allocator_t
  144. = typename associated_allocator<T, Allocator>::type;
  145. #endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
  146. namespace detail {
  147. template <typename T, typename A, typename = void>
  148. struct associated_allocator_forwarding_base
  149. {
  150. };
  151. template <typename T, typename A>
  152. struct associated_allocator_forwarding_base<T, A,
  153. typename enable_if<
  154. is_same<
  155. typename associated_allocator<T,
  156. A>::asio_associated_allocator_is_unspecialised,
  157. void
  158. >::value
  159. >::type>
  160. {
  161. typedef void asio_associated_allocator_is_unspecialised;
  162. };
  163. } // namespace detail
  164. #if defined(BOOST_ASIO_HAS_STD_REFERENCE_WRAPPER) \
  165. || defined(GENERATING_DOCUMENTATION)
  166. /// Specialisation of associated_allocator for @c std::reference_wrapper.
  167. template <typename T, typename Allocator>
  168. struct associated_allocator<reference_wrapper<T>, Allocator>
  169. #if !defined(GENERATING_DOCUMENTATION)
  170. : detail::associated_allocator_forwarding_base<T, Allocator>
  171. #endif // !defined(GENERATING_DOCUMENTATION)
  172. {
  173. /// Forwards @c type to the associator specialisation for the unwrapped type
  174. /// @c T.
  175. typedef typename associated_allocator<T, Allocator>::type type;
  176. /// Forwards the request to get the allocator to the associator specialisation
  177. /// for the unwrapped type @c T.
  178. static type get(reference_wrapper<T> t) BOOST_ASIO_NOEXCEPT
  179. {
  180. return associated_allocator<T, Allocator>::get(t.get());
  181. }
  182. /// Forwards the request to get the allocator to the associator specialisation
  183. /// for the unwrapped type @c T.
  184. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(
  185. reference_wrapper<T> t, const Allocator& a) BOOST_ASIO_NOEXCEPT
  186. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  187. associated_allocator<T, Allocator>::get(t.get(), a)))
  188. {
  189. return associated_allocator<T, Allocator>::get(t.get(), a);
  190. }
  191. };
  192. #endif // defined(BOOST_ASIO_HAS_STD_REFERENCE_WRAPPER)
  193. // || defined(GENERATING_DOCUMENTATION)
  194. } // namespace asio
  195. } // namespace boost
  196. #include <boost/asio/detail/pop_options.hpp>
  197. #endif // BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP