]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/type_traits.hpp
f5e466a7598800becc6a96485f1c1e7df5cfe4d6
[ceph.git] / ceph / src / boost / boost / beast / core / 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_TYPE_TRAITS_HPP
11 #define BOOST_BEAST_TYPE_TRAITS_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/file_base.hpp>
15 #include <boost/beast/core/detail/type_traits.hpp>
16 #include <boost/asio/buffer.hpp>
17 #include <type_traits>
18
19 namespace boost {
20 namespace beast {
21
22 //------------------------------------------------------------------------------
23 //
24 // Handler concepts
25 //
26 //------------------------------------------------------------------------------
27
28 /** Determine if `T` meets the requirements of @b CompletionHandler.
29
30 This trait checks whether a type meets the requirements for a completion
31 handler, and is also callable with the specified signature.
32 Metafunctions are used to perform compile time checking of template
33 types. This type will be `std::true_type` if `T` meets the requirements,
34 else the type will be `std::false_type`.
35
36 @par Example
37
38 Use with `static_assert`:
39
40 @code
41 struct handler
42 {
43 void operator()(error_code&);
44 };
45
46 static_assert(is_completion_handler<handler, void(error_code&)>::value,
47 "Not a completion handler");
48 @endcode
49 */
50 template<class T, class Signature>
51 #if BOOST_BEAST_DOXYGEN
52 using is_completion_handler = std::integral_constant<bool, ...>;
53 #else
54 using is_completion_handler = std::integral_constant<bool,
55 std::is_move_constructible<typename std::decay<T>::type>::value &&
56 detail::is_invocable<T, Signature>::value>;
57 #endif
58
59 //------------------------------------------------------------------------------
60 //
61 // Stream concepts
62 //
63 //------------------------------------------------------------------------------
64
65 /** Determine if `T` has the `get_executor` member function.
66
67 Metafunctions are used to perform compile time checking of template
68 types. This type will be `std::true_type` if `T` has the member
69 function with the correct signature, else type will be `std::false_type`.
70
71 @par Example
72
73 Use with tag dispatching:
74
75 @code
76 template<class T>
77 void maybe_hello(T& t, std::true_type)
78 {
79 boost::asio::post(
80 t.get_executor(),
81 []
82 {
83 std::cout << "Hello, world!" << std::endl;
84 });
85 }
86
87 template<class T>
88 void maybe_hello(T&, std::false_type)
89 {
90 // T does not have get_executor
91 }
92
93 template<class T>
94 void maybe_hello(T& t)
95 {
96 maybe_hello(t, has_get_executor<T>{});
97 }
98 @endcode
99
100 Use with `static_assert`:
101
102 @code
103 struct stream
104 {
105 using executor_type = boost::asio::io_context::executor_type;
106 executor_type get_executor() noexcept;
107 };
108
109 static_assert(has_get_executor<stream>::value, "Missing get_executor member");
110 @endcode
111 */
112 #if BOOST_BEAST_DOXYGEN
113 template<class T>
114 struct has_get_executor : std::integral_constant<bool, ...>{};
115 #else
116 template<class T, class = void>
117 struct has_get_executor : std::false_type {};
118
119 template<class T>
120 struct has_get_executor<T, beast::detail::void_t<decltype(
121 std::declval<T&>().get_executor(),
122 (void)0)>> : std::true_type {};
123 #endif
124
125 /** Alias for `T::lowest_layer_type` if it exists, else `T`
126
127 This will be a type alias for `T::lowest_layer_type`
128 if it exists, else it will be an alias for `T`.
129
130 @par Example
131
132 Declaring a wrapper:
133
134 @code
135 template<class Stream>
136 struct stream_wrapper
137 {
138 using next_layer_type = typename std::remove_reference<Stream>::type;
139 using lowest_layer_type = get_lowest_layer<stream_type>;
140 };
141 @endcode
142
143 Defining a metafunction:
144
145 @code
146 /// Alias for `std::true_type` if `T` wraps another stream
147 template<class T>
148 using is_stream_wrapper : std::integral_constant<bool,
149 ! std::is_same<T, get_lowest_layer<T>>::value> {};
150 @endcode
151 */
152 #if BOOST_BEAST_DOXYGEN
153 template<class T>
154 struct get_lowest_layer;
155 #else
156 template<class T>
157 using get_lowest_layer = typename detail::get_lowest_layer_helper<T>::type;
158 #endif
159
160 /** Determine if `T` meets the requirements of @b AsyncReadStream.
161
162 Metafunctions are used to perform compile time checking of template
163 types. This type will be `std::true_type` if `T` meets the requirements,
164 else the type will be `std::false_type`.
165
166 @par Example
167
168 Use with `static_assert`:
169
170 @code
171 template<class AsyncReadStream>
172 void f(AsyncReadStream& stream)
173 {
174 static_assert(is_async_read_stream<AsyncReadStream>::value,
175 "AsyncReadStream requirements not met");
176 ...
177 @endcode
178
179 Use with `std::enable_if` (SFINAE):
180
181 @code
182 template<class AsyncReadStream>
183 typename std::enable_if<is_async_read_stream<AsyncReadStream>::value>::type
184 f(AsyncReadStream& stream);
185 @endcode
186 */
187 #if BOOST_BEAST_DOXYGEN
188 template<class T>
189 struct is_async_read_stream : std::integral_constant<bool, ...>{};
190 #else
191 template<class T, class = void>
192 struct is_async_read_stream : std::false_type {};
193
194 template<class T>
195 struct is_async_read_stream<T, detail::void_t<decltype(
196 std::declval<T>().async_read_some(
197 std::declval<detail::MutableBufferSequence>(),
198 std::declval<detail::ReadHandler>()),
199 (void)0)>> : std::integral_constant<bool,
200 has_get_executor<T>::value
201 > {};
202 #endif
203
204 /** Determine if `T` meets the requirements of @b AsyncWriteStream.
205
206 Metafunctions are used to perform compile time checking of template
207 types. This type will be `std::true_type` if `T` meets the requirements,
208 else the type will be `std::false_type`.
209
210 @par Example
211
212 Use with `static_assert`:
213
214 @code
215 template<class AsyncWriteStream>
216 void f(AsyncWriteStream& stream)
217 {
218 static_assert(is_async_write_stream<AsyncWriteStream>::value,
219 "AsyncWriteStream requirements not met");
220 ...
221 @endcode
222
223 Use with `std::enable_if` (SFINAE):
224
225 @code
226 template<class AsyncWriteStream>
227 typename std::enable_if<is_async_write_stream<AsyncWriteStream>::value>::type
228 f(AsyncWriteStream& stream);
229 @endcode
230 */
231 #if BOOST_BEAST_DOXYGEN
232 template<class T>
233 struct is_async_write_stream : std::integral_constant<bool, ...>{};
234 #else
235 template<class T, class = void>
236 struct is_async_write_stream : std::false_type {};
237
238 template<class T>
239 struct is_async_write_stream<T, detail::void_t<decltype(
240 std::declval<T>().async_write_some(
241 std::declval<detail::ConstBufferSequence>(),
242 std::declval<detail::WriteHandler>()),
243 (void)0)>> : std::integral_constant<bool,
244 has_get_executor<T>::value
245 > {};
246 #endif
247
248 /** Determine if `T` meets the requirements of @b SyncReadStream.
249
250 Metafunctions are used to perform compile time checking of template
251 types. This type will be `std::true_type` if `T` meets the requirements,
252 else the type will be `std::false_type`.
253
254 @par Example
255
256 Use with `static_assert`:
257
258 @code
259 template<class SyncReadStream>
260 void f(SyncReadStream& stream)
261 {
262 static_assert(is_sync_read_stream<SyncReadStream>::value,
263 "SyncReadStream requirements not met");
264 ...
265 @endcode
266
267 Use with `std::enable_if` (SFINAE):
268
269 @code
270 template<class SyncReadStream>
271 typename std::enable_if<is_sync_read_stream<SyncReadStream>::value>::type
272 f(SyncReadStream& stream);
273 @endcode
274 */
275 #if BOOST_BEAST_DOXYGEN
276 template<class T>
277 struct is_sync_read_stream : std::integral_constant<bool, ...>{};
278 #else
279 template<class T, class = void>
280 struct is_sync_read_stream : std::false_type {};
281
282 template<class T>
283 struct is_sync_read_stream<T, detail::void_t<decltype(
284 std::declval<std::size_t&>() = std::declval<T>().read_some(
285 std::declval<detail::MutableBufferSequence>()),
286 std::declval<std::size_t&>() = std::declval<T>().read_some(
287 std::declval<detail::MutableBufferSequence>(),
288 std::declval<boost::system::error_code&>()),
289 (void)0)>> : std::true_type {};
290 #endif
291
292 /** Determine if `T` meets the requirements of @b SyncWriteStream.
293
294 Metafunctions are used to perform compile time checking of template
295 types. This type will be `std::true_type` if `T` meets the requirements,
296 else the type will be `std::false_type`.
297
298 @par Example
299
300 Use with `static_assert`:
301
302 @code
303 template<class SyncReadStream>
304 void f(SyncReadStream& stream)
305 {
306 static_assert(is_sync_read_stream<SyncReadStream>::value,
307 "SyncReadStream requirements not met");
308 ...
309 @endcode
310
311 Use with `std::enable_if` (SFINAE):
312
313 @code
314 template<class SyncReadStream>
315 typename std::enable_if<is_sync_read_stream<SyncReadStream>::value>::type
316 f(SyncReadStream& stream);
317 @endcode
318 */
319 #if BOOST_BEAST_DOXYGEN
320 template<class T>
321 struct is_sync_write_stream : std::integral_constant<bool, ...>{};
322 #else
323 template<class T, class = void>
324 struct is_sync_write_stream : std::false_type {};
325
326 template<class T>
327 struct is_sync_write_stream<T, detail::void_t<decltype(
328 std::declval<std::size_t&>() = std::declval<T&>().write_some(
329 std::declval<detail::ConstBufferSequence>()),
330 std::declval<std::size_t&>() = std::declval<T&>().write_some(
331 std::declval<detail::ConstBufferSequence>(),
332 std::declval<boost::system::error_code&>()),
333 (void)0)>> : std::true_type {};
334 #endif
335
336 /** Determine if `T` meets the requirements of @b AsyncStream.
337
338 Metafunctions are used to perform compile time checking of template
339 types. This type will be `std::true_type` if `T` meets the requirements,
340 else the type will be `std::false_type`.
341
342 @par Example
343
344 Use with `static_assert`:
345
346 @code
347 template<class AsyncStream>
348 void f(AsyncStream& stream)
349 {
350 static_assert(is_async_stream<AsyncStream>::value,
351 "AsyncStream requirements not met");
352 ...
353 @endcode
354
355 Use with `std::enable_if` (SFINAE):
356
357 @code
358 template<class AsyncStream>
359 typename std::enable_if<is_async_stream<AsyncStream>::value>::type
360 f(AsyncStream& stream);
361 @endcode
362 */
363 #if BOOST_BEAST_DOXYGEN
364 template<class T>
365 struct is_async_stream : std::integral_constant<bool, ...>{};
366 #else
367 template<class T>
368 using is_async_stream = std::integral_constant<bool,
369 is_async_read_stream<T>::value && is_async_write_stream<T>::value>;
370 #endif
371
372 /** Determine if `T` meets the requirements of @b SyncStream.
373
374 Metafunctions are used to perform compile time checking of template
375 types. This type will be `std::true_type` if `T` meets the requirements,
376 else the type will be `std::false_type`.
377
378 @par Example
379
380 Use with `static_assert`:
381
382 @code
383 template<class SyncStream>
384 void f(SyncStream& stream)
385 {
386 static_assert(is_sync_stream<SyncStream>::value,
387 "SyncStream requirements not met");
388 ...
389 @endcode
390
391 Use with `std::enable_if` (SFINAE):
392
393 @code
394 template<class SyncStream>
395 typename std::enable_if<is_sync_stream<SyncStream>::value>::type
396 f(SyncStream& stream);
397 @endcode
398 */
399 #if BOOST_BEAST_DOXYGEN
400 template<class T>
401 struct is_sync_stream : std::integral_constant<bool, ...>{};
402 #else
403 template<class T>
404 using is_sync_stream = std::integral_constant<bool,
405 is_sync_read_stream<T>::value && is_sync_write_stream<T>::value>;
406 #endif
407
408 //------------------------------------------------------------------------------
409 //
410 // File concepts
411 //
412 //------------------------------------------------------------------------------
413
414 /** Determine if `T` meets the requirements of @b File.
415
416 Metafunctions are used to perform compile time checking of template
417 types. This type will be `std::true_type` if `T` meets the requirements,
418 else the type will be `std::false_type`.
419
420 @par Example
421
422 Use with `static_assert`:
423
424 @code
425 template<class File>
426 void f(File& file)
427 {
428 static_assert(is_file<File>::value,
429 "File requirements not met");
430 ...
431 @endcode
432
433 Use with `std::enable_if` (SFINAE):
434
435 @code
436 template<class File>
437 typename std::enable_if<is_file<File>::value>::type
438 f(File& file);
439 @endcode
440 */
441 #if BOOST_BEAST_DOXYGEN
442 template<class T>
443 struct is_file : std::integral_constant<bool, ...>{};
444 #else
445 template<class T, class = void>
446 struct is_file : std::false_type {};
447
448 template<class T>
449 struct is_file<T, detail::void_t<decltype(
450 std::declval<bool&>() = std::declval<T const&>().is_open(),
451 std::declval<T&>().close(std::declval<error_code&>()),
452 std::declval<T&>().open(
453 std::declval<char const*>(),
454 std::declval<file_mode>(),
455 std::declval<error_code&>()),
456 std::declval<std::uint64_t&>() = std::declval<T&>().size(
457 std::declval<error_code&>()),
458 std::declval<std::uint64_t&>() = std::declval<T&>().pos(
459 std::declval<error_code&>()),
460 std::declval<T&>().seek(
461 std::declval<std::uint64_t>(),
462 std::declval<error_code&>()),
463 std::declval<std::size_t&>() = std::declval<T&>().read(
464 std::declval<void*>(),
465 std::declval<std::size_t>(),
466 std::declval<error_code&>()),
467 std::declval<std::size_t&>() = std::declval<T&>().write(
468 std::declval<void const*>(),
469 std::declval<std::size_t>(),
470 std::declval<error_code&>()),
471 (void)0)>> : std::integral_constant<bool,
472 std::is_default_constructible<T>::value &&
473 std::is_destructible<T>::value
474 > {};
475 #endif
476
477 } // beast
478 } // boost
479
480 #endif