2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_TYPE_TRAITS_HPP
11 #define BOOST_BEAST_TYPE_TRAITS_HPP
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>
22 //------------------------------------------------------------------------------
26 //------------------------------------------------------------------------------
28 /** Determine if `T` meets the requirements of @b CompletionHandler.
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`.
38 Use with `static_assert`:
43 void operator()(error_code&);
46 static_assert(is_completion_handler<handler, void(error_code&)>::value,
47 "Not a completion handler");
50 template<class T, class Signature>
51 #if BOOST_BEAST_DOXYGEN
52 using is_completion_handler = std::integral_constant<bool, ...>;
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>;
59 //------------------------------------------------------------------------------
63 //------------------------------------------------------------------------------
65 /** Determine if `T` has the `get_executor` member function.
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`.
73 Use with tag dispatching:
77 void maybe_hello(T& t, std::true_type)
83 std::cout << "Hello, world!" << std::endl;
88 void maybe_hello(T&, std::false_type)
90 // T does not have get_executor
94 void maybe_hello(T& t)
96 maybe_hello(t, has_get_executor<T>{});
100 Use with `static_assert`:
105 using executor_type = boost::asio::io_context::executor_type;
106 executor_type get_executor() noexcept;
109 static_assert(has_get_executor<stream>::value, "Missing get_executor member");
112 #if BOOST_BEAST_DOXYGEN
114 struct has_get_executor : std::integral_constant<bool, ...>{};
116 template<class T, class = void>
117 struct has_get_executor : std::false_type {};
120 struct has_get_executor<T, beast::detail::void_t<decltype(
121 std::declval<T&>().get_executor(),
122 (void)0)>> : std::true_type {};
125 /** Alias for `T::lowest_layer_type` if it exists, else `T`
127 This will be a type alias for `T::lowest_layer_type`
128 if it exists, else it will be an alias for `T`.
135 template<class Stream>
136 struct stream_wrapper
138 using next_layer_type = typename std::remove_reference<Stream>::type;
139 using lowest_layer_type = get_lowest_layer<stream_type>;
143 Defining a metafunction:
146 /// Alias for `std::true_type` if `T` wraps another stream
148 using is_stream_wrapper : std::integral_constant<bool,
149 ! std::is_same<T, get_lowest_layer<T>>::value> {};
152 #if BOOST_BEAST_DOXYGEN
154 struct get_lowest_layer;
157 using get_lowest_layer = typename detail::get_lowest_layer_helper<T>::type;
160 /** Determine if `T` meets the requirements of @b AsyncReadStream.
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`.
168 Use with `static_assert`:
171 template<class AsyncReadStream>
172 void f(AsyncReadStream& stream)
174 static_assert(is_async_read_stream<AsyncReadStream>::value,
175 "AsyncReadStream requirements not met");
179 Use with `std::enable_if` (SFINAE):
182 template<class AsyncReadStream>
183 typename std::enable_if<is_async_read_stream<AsyncReadStream>::value>::type
184 f(AsyncReadStream& stream);
187 #if BOOST_BEAST_DOXYGEN
189 struct is_async_read_stream : std::integral_constant<bool, ...>{};
191 template<class T, class = void>
192 struct is_async_read_stream : std::false_type {};
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
204 /** Determine if `T` meets the requirements of @b AsyncWriteStream.
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`.
212 Use with `static_assert`:
215 template<class AsyncWriteStream>
216 void f(AsyncWriteStream& stream)
218 static_assert(is_async_write_stream<AsyncWriteStream>::value,
219 "AsyncWriteStream requirements not met");
223 Use with `std::enable_if` (SFINAE):
226 template<class AsyncWriteStream>
227 typename std::enable_if<is_async_write_stream<AsyncWriteStream>::value>::type
228 f(AsyncWriteStream& stream);
231 #if BOOST_BEAST_DOXYGEN
233 struct is_async_write_stream : std::integral_constant<bool, ...>{};
235 template<class T, class = void>
236 struct is_async_write_stream : std::false_type {};
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
248 /** Determine if `T` meets the requirements of @b SyncReadStream.
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`.
256 Use with `static_assert`:
259 template<class SyncReadStream>
260 void f(SyncReadStream& stream)
262 static_assert(is_sync_read_stream<SyncReadStream>::value,
263 "SyncReadStream requirements not met");
267 Use with `std::enable_if` (SFINAE):
270 template<class SyncReadStream>
271 typename std::enable_if<is_sync_read_stream<SyncReadStream>::value>::type
272 f(SyncReadStream& stream);
275 #if BOOST_BEAST_DOXYGEN
277 struct is_sync_read_stream : std::integral_constant<bool, ...>{};
279 template<class T, class = void>
280 struct is_sync_read_stream : std::false_type {};
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 {};
292 /** Determine if `T` meets the requirements of @b SyncWriteStream.
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`.
300 Use with `static_assert`:
303 template<class SyncReadStream>
304 void f(SyncReadStream& stream)
306 static_assert(is_sync_read_stream<SyncReadStream>::value,
307 "SyncReadStream requirements not met");
311 Use with `std::enable_if` (SFINAE):
314 template<class SyncReadStream>
315 typename std::enable_if<is_sync_read_stream<SyncReadStream>::value>::type
316 f(SyncReadStream& stream);
319 #if BOOST_BEAST_DOXYGEN
321 struct is_sync_write_stream : std::integral_constant<bool, ...>{};
323 template<class T, class = void>
324 struct is_sync_write_stream : std::false_type {};
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 {};
336 /** Determine if `T` meets the requirements of @b AsyncStream.
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`.
344 Use with `static_assert`:
347 template<class AsyncStream>
348 void f(AsyncStream& stream)
350 static_assert(is_async_stream<AsyncStream>::value,
351 "AsyncStream requirements not met");
355 Use with `std::enable_if` (SFINAE):
358 template<class AsyncStream>
359 typename std::enable_if<is_async_stream<AsyncStream>::value>::type
360 f(AsyncStream& stream);
363 #if BOOST_BEAST_DOXYGEN
365 struct is_async_stream : std::integral_constant<bool, ...>{};
368 using is_async_stream = std::integral_constant<bool,
369 is_async_read_stream<T>::value && is_async_write_stream<T>::value>;
372 /** Determine if `T` meets the requirements of @b SyncStream.
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`.
380 Use with `static_assert`:
383 template<class SyncStream>
384 void f(SyncStream& stream)
386 static_assert(is_sync_stream<SyncStream>::value,
387 "SyncStream requirements not met");
391 Use with `std::enable_if` (SFINAE):
394 template<class SyncStream>
395 typename std::enable_if<is_sync_stream<SyncStream>::value>::type
396 f(SyncStream& stream);
399 #if BOOST_BEAST_DOXYGEN
401 struct is_sync_stream : std::integral_constant<bool, ...>{};
404 using is_sync_stream = std::integral_constant<bool,
405 is_sync_read_stream<T>::value && is_sync_write_stream<T>::value>;
408 //------------------------------------------------------------------------------
412 //------------------------------------------------------------------------------
414 /** Determine if `T` meets the requirements of @b File.
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`.
422 Use with `static_assert`:
428 static_assert(is_file<File>::value,
429 "File requirements not met");
433 Use with `std::enable_if` (SFINAE):
437 typename std::enable_if<is_file<File>::value>::type
441 #if BOOST_BEAST_DOXYGEN
443 struct is_file : std::integral_constant<bool, ...>{};
445 template<class T, class = void>
446 struct is_file : std::false_type {};
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