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

source code of boost/libs/asio/include/boost/asio/associated_allocator.hpp