]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/detail/type_traits.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / core / detail / type_traits.hpp
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP
11 #define BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP
12
13 #include <boost/beast/core/error.hpp>
14 #include <boost/asio/buffer.hpp>
15 #include <iterator>
16 #include <tuple>
17 #include <type_traits>
18 #include <string>
19 #include <utility>
20
21 namespace boost {
22 namespace beast {
23 namespace detail {
24
25 //
26 // utilities
27 //
28
29 template<class... Ts>
30 struct make_void
31 {
32 using type = void;
33 };
34
35 template<class... Ts>
36 using void_t = typename make_void<Ts...>::type;
37
38 template<class T>
39 inline
40 void
41 accept_rv(T){}
42
43 template<class U>
44 std::size_t constexpr
45 max_sizeof()
46 {
47 return sizeof(U);
48 }
49
50 template<class U0, class U1, class... Us>
51 std::size_t constexpr
52 max_sizeof()
53 {
54 return
55 max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
56 max_sizeof<U0>() : max_sizeof<U1, Us...>();
57 }
58
59 template<class U>
60 std::size_t constexpr
61 max_alignof()
62 {
63 return alignof(U);
64 }
65
66 template<class U0, class U1, class... Us>
67 std::size_t constexpr
68 max_alignof()
69 {
70 return
71 max_alignof<U0>() > max_alignof<U1, Us...>() ?
72 max_alignof<U0>() : max_alignof<U1, Us...>();
73 }
74
75 template<unsigned N, class T, class... Tn>
76 struct repeat_tuple_impl
77 {
78 using type = typename repeat_tuple_impl<
79 N - 1, T, T, Tn...>::type;
80 };
81
82 template<class T, class... Tn>
83 struct repeat_tuple_impl<0, T, Tn...>
84 {
85 using type = std::tuple<T, Tn...>;
86 };
87
88 template<unsigned N, class T>
89 struct repeat_tuple
90 {
91 using type =
92 typename repeat_tuple_impl<N-1, T>::type;
93 };
94
95 template<class T>
96 struct repeat_tuple<0, T>
97 {
98 using type = std::tuple<>;
99 };
100
101 template<class R, class C, class ...A>
102 auto
103 is_invocable_test(C&& c, int, A&& ...a)
104 -> decltype(std::is_convertible<
105 decltype(c(std::forward<A>(a)...)), R>::value ||
106 std::is_same<R, void>::value,
107 std::true_type());
108
109 template<class R, class C, class ...A>
110 std::false_type
111 is_invocable_test(C&& c, long, A&& ...a);
112
113 /** Metafunction returns `true` if F callable as R(A...)
114
115 Example:
116
117 @code
118 is_invocable<T, void(std::string)>
119 @endcode
120 */
121 /** @{ */
122 template<class C, class F>
123 struct is_invocable : std::false_type
124 {
125 };
126
127 template<class C, class R, class ...A>
128 struct is_invocable<C, R(A...)>
129 : decltype(is_invocable_test<R>(
130 std::declval<C>(), 1, std::declval<A>()...))
131 {
132 };
133 /** @} */
134
135 // for span
136 template<class T, class E, class = void>
137 struct is_contiguous_container: std::false_type {};
138
139 template<class T, class E>
140 struct is_contiguous_container<T, E, void_t<
141 decltype(
142 std::declval<std::size_t&>() = std::declval<T const&>().size(),
143 std::declval<E*&>() = std::declval<T&>().data(),
144 (void)0),
145 typename std::enable_if<
146 std::is_same<
147 typename std::remove_cv<E>::type,
148 typename std::remove_cv<
149 typename std::remove_pointer<
150 decltype(std::declval<T&>().data())
151 >::type
152 >::type
153 >::value
154 >::type>>: std::true_type
155 {};
156
157 template<class...>
158 struct unwidest_unsigned;
159
160 template<class U0>
161 struct unwidest_unsigned<U0>
162 {
163 using type = U0;
164 };
165
166 template<class U0, class... UN>
167 struct unwidest_unsigned<U0, UN...>
168 {
169 BOOST_STATIC_ASSERT(std::is_unsigned<U0>::value);
170 using type = typename std::conditional<
171 (sizeof(U0) < sizeof(typename unwidest_unsigned<UN...>::type)),
172 U0, typename unwidest_unsigned<UN...>::type>::type;
173 };
174
175 template<class...>
176 struct widest_unsigned;
177
178 template<class U0>
179 struct widest_unsigned<U0>
180 {
181 using type = U0;
182 };
183
184 template<class U0, class... UN>
185 struct widest_unsigned<U0, UN...>
186 {
187 BOOST_STATIC_ASSERT(std::is_unsigned<U0>::value);
188 using type = typename std::conditional<
189 (sizeof(U0) > sizeof(typename widest_unsigned<UN...>::type)),
190 U0, typename widest_unsigned<UN...>::type>::type;
191 };
192
193 template<class U>
194 inline
195 constexpr
196 U
197 min_all(U u)
198 {
199 BOOST_STATIC_ASSERT(std::is_unsigned<U>::value);
200 return u;
201 }
202
203 template<class U0, class U1, class... UN>
204 inline
205 constexpr
206 typename unwidest_unsigned<U0, U1, UN...>::type
207 min_all(U0 u0, U1 u1, UN... un)
208 {
209 using type =
210 typename unwidest_unsigned<U0, U1, UN...>::type;
211 return u0 < u1 ?
212 static_cast<type>(min_all(u0, un...)) :
213 static_cast<type>(min_all(u1, un...));
214 }
215
216 template<class U>
217 inline
218 constexpr
219 U
220 max_all(U u)
221 {
222 BOOST_STATIC_ASSERT(std::is_unsigned<U>::value);
223 return u;
224 }
225
226 template<class U0, class U1, class... UN>
227 inline
228 constexpr
229 typename widest_unsigned<U0, U1, UN...>::type
230 max_all(U0 u0, U1 u1, UN... un)
231 {
232 return u0 > u1? max_all(u0, un...) : max_all(u1, un...);
233 }
234
235 //------------------------------------------------------------------------------
236
237 //
238 // buffer concepts
239 //
240
241 // Types that meet the requirements,
242 // for use with std::declval only.
243 template<class BufferType>
244 struct BufferSequence
245 {
246 using value_type = BufferType;
247 using const_iterator = BufferType const*;
248 ~BufferSequence();
249 BufferSequence(BufferSequence const&) = default;
250 const_iterator begin() const noexcept;
251 const_iterator end() const noexcept;
252 };
253 using ConstBufferSequence =
254 BufferSequence<boost::asio::const_buffer>;
255 using MutableBufferSequence =
256 BufferSequence<boost::asio::mutable_buffer>;
257
258 template<class B1, class... Bn>
259 struct is_all_const_buffer_sequence
260 : std::integral_constant<bool,
261 boost::asio::is_const_buffer_sequence<B1>::value &&
262 is_all_const_buffer_sequence<Bn...>::value>
263 {
264 };
265
266 template<class B>
267 struct is_all_const_buffer_sequence<B>
268 : boost::asio::is_const_buffer_sequence<B>
269 {
270 };
271
272 template<class... Bn>
273 struct common_buffers_type
274 {
275 using type = typename std::conditional<
276 std::is_convertible<std::tuple<Bn...>,
277 typename repeat_tuple<sizeof...(Bn),
278 boost::asio::mutable_buffer>::type>::value,
279 boost::asio::mutable_buffer,
280 boost::asio::const_buffer>::type;
281 };
282
283 template<class B>
284 struct buffer_sequence_iterator
285 {
286 using type = decltype(
287 boost::asio::buffer_sequence_begin(
288 std::declval<B const&>()));
289 };
290
291 // Types that meet the requirements,
292 // for use with std::declval only.
293 struct StreamHandler
294 {
295 StreamHandler(StreamHandler const&) = default;
296 void operator()(error_code ec, std::size_t);
297 };
298 using ReadHandler = StreamHandler;
299 using WriteHandler = StreamHandler;
300
301 template<class Buffers>
302 class buffers_range_adapter
303 {
304 Buffers const& b_;
305
306 public:
307 using value_type = typename std::conditional<
308 std::is_convertible<typename std::iterator_traits<
309 typename buffer_sequence_iterator<Buffers>::type>::value_type,
310 boost::asio::const_buffer>::value,
311 boost::asio::const_buffer,
312 boost::asio::mutable_buffer>::type;
313
314 /* VFALCO This isn't right, because range-for will pick up the iterator's
315 value_type which might not be const_buffer or mutable_buffer. We
316 need to declare our own iterator wrapper that converts the underlying
317 iterator's value_type to const_buffer or mutable_buffer so that
318 range-for sees one of those types.
319 */
320 using const_iterator = typename
321 buffer_sequence_iterator<Buffers>::type;
322
323 explicit
324 buffers_range_adapter(Buffers const& b)
325 : b_(b)
326 {
327 }
328
329 const_iterator
330 begin() const noexcept
331 {
332 return boost::asio::buffer_sequence_begin(b_);
333 }
334
335 const_iterator
336 end() const noexcept
337 {
338 return boost::asio::buffer_sequence_end(b_);
339 }
340 };
341
342 template<class Buffers>
343 buffers_range_adapter<Buffers>
344 buffers_range(Buffers const& buffers)
345 {
346 return buffers_range_adapter<Buffers>{buffers};
347 }
348
349 } // detail
350 } // beast
351 } // boost
352
353 #endif