associated_allocator.hpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. //
  2. // associated_allocator.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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, void_t<typename T::allocator_type>> : true_type
  32. {
  33. };
  34. template <typename T, typename A, typename = void, typename = void>
  35. struct associated_allocator_impl
  36. {
  37. typedef void asio_associated_allocator_is_unspecialised;
  38. typedef A type;
  39. static type get(const T&) noexcept
  40. {
  41. return type();
  42. }
  43. static const type& get(const T&, const A& a) noexcept
  44. {
  45. return a;
  46. }
  47. };
  48. template <typename T, typename A>
  49. struct associated_allocator_impl<T, A, void_t<typename T::allocator_type>>
  50. {
  51. typedef typename T::allocator_type type;
  52. static auto get(const T& t) noexcept
  53. -> decltype(t.get_allocator())
  54. {
  55. return t.get_allocator();
  56. }
  57. static auto get(const T& t, const A&) noexcept
  58. -> decltype(t.get_allocator())
  59. {
  60. return t.get_allocator();
  61. }
  62. };
  63. template <typename T, typename A>
  64. struct associated_allocator_impl<T, A,
  65. enable_if_t<
  66. !has_allocator_type<T>::value
  67. >,
  68. void_t<
  69. typename associator<associated_allocator, T, A>::type
  70. >> : associator<associated_allocator, T, A>
  71. {
  72. };
  73. } // namespace detail
  74. /// Traits type used to obtain the allocator associated with an object.
  75. /**
  76. * A program may specialise this traits type if the @c T template parameter in
  77. * the specialisation is a user-defined type. The template parameter @c
  78. * Allocator shall be a type meeting the Allocator requirements.
  79. *
  80. * Specialisations shall meet the following requirements, where @c t is a const
  81. * reference to an object of type @c T, and @c a is an object of type @c
  82. * Allocator.
  83. *
  84. * @li Provide a nested typedef @c type that identifies a type meeting the
  85. * Allocator requirements.
  86. *
  87. * @li Provide a noexcept static member function named @c get, callable as @c
  88. * get(t) and with return type @c type or a (possibly const) reference to @c
  89. * type.
  90. *
  91. * @li Provide a noexcept static member function named @c get, callable as @c
  92. * get(t,a) and with return type @c type or a (possibly const) reference to @c
  93. * type.
  94. */
  95. template <typename T, typename Allocator = std::allocator<void>>
  96. struct associated_allocator
  97. #if !defined(GENERATING_DOCUMENTATION)
  98. : detail::associated_allocator_impl<T, Allocator>
  99. #endif // !defined(GENERATING_DOCUMENTATION)
  100. {
  101. #if defined(GENERATING_DOCUMENTATION)
  102. /// If @c T has a nested type @c allocator_type, <tt>T::allocator_type</tt>.
  103. /// Otherwise @c Allocator.
  104. typedef see_below type;
  105. /// If @c T has a nested type @c allocator_type, returns
  106. /// <tt>t.get_allocator()</tt>. Otherwise returns @c type().
  107. static decltype(auto) get(const T& t) noexcept;
  108. /// If @c T has a nested type @c allocator_type, returns
  109. /// <tt>t.get_allocator()</tt>. Otherwise returns @c a.
  110. static decltype(auto) get(const T& t, const Allocator& a) noexcept;
  111. #endif // defined(GENERATING_DOCUMENTATION)
  112. };
  113. /// Helper function to obtain an object's associated allocator.
  114. /**
  115. * @returns <tt>associated_allocator<T>::get(t)</tt>
  116. */
  117. template <typename T>
  118. BOOST_ASIO_NODISCARD inline typename associated_allocator<T>::type
  119. get_associated_allocator(const T& t) noexcept
  120. {
  121. return associated_allocator<T>::get(t);
  122. }
  123. /// Helper function to obtain an object's associated allocator.
  124. /**
  125. * @returns <tt>associated_allocator<T, Allocator>::get(t, a)</tt>
  126. */
  127. template <typename T, typename Allocator>
  128. BOOST_ASIO_NODISCARD inline auto get_associated_allocator(
  129. const T& t, const Allocator& a) noexcept
  130. -> decltype(associated_allocator<T, Allocator>::get(t, a))
  131. {
  132. return associated_allocator<T, Allocator>::get(t, a);
  133. }
  134. template <typename T, typename Allocator = std::allocator<void>>
  135. using associated_allocator_t
  136. = typename associated_allocator<T, Allocator>::type;
  137. namespace detail {
  138. template <typename T, typename A, typename = void>
  139. struct associated_allocator_forwarding_base
  140. {
  141. };
  142. template <typename T, typename A>
  143. struct associated_allocator_forwarding_base<T, A,
  144. enable_if_t<
  145. is_same<
  146. typename associated_allocator<T,
  147. A>::asio_associated_allocator_is_unspecialised,
  148. void
  149. >::value
  150. >>
  151. {
  152. typedef void asio_associated_allocator_is_unspecialised;
  153. };
  154. } // namespace detail
  155. /// Specialisation of associated_allocator for @c std::reference_wrapper.
  156. template <typename T, typename Allocator>
  157. struct associated_allocator<reference_wrapper<T>, Allocator>
  158. #if !defined(GENERATING_DOCUMENTATION)
  159. : detail::associated_allocator_forwarding_base<T, Allocator>
  160. #endif // !defined(GENERATING_DOCUMENTATION)
  161. {
  162. /// Forwards @c type to the associator specialisation for the unwrapped type
  163. /// @c T.
  164. typedef typename associated_allocator<T, Allocator>::type type;
  165. /// Forwards the request to get the allocator to the associator specialisation
  166. /// for the unwrapped type @c T.
  167. static type get(reference_wrapper<T> t) noexcept
  168. {
  169. return associated_allocator<T, Allocator>::get(t.get());
  170. }
  171. /// Forwards the request to get the allocator to the associator specialisation
  172. /// for the unwrapped type @c T.
  173. static auto get(reference_wrapper<T> t, const Allocator& a) noexcept
  174. -> decltype(associated_allocator<T, Allocator>::get(t.get(), a))
  175. {
  176. return associated_allocator<T, Allocator>::get(t.get(), a);
  177. }
  178. };
  179. } // namespace asio
  180. } // namespace boost
  181. #include <boost/asio/detail/pop_options.hpp>
  182. #endif // BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP