summaryrefslogtreecommitdiff
path: root/boost/beast/core/type_traits.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/core/type_traits.hpp')
-rw-r--r--boost/beast/core/type_traits.hpp490
1 files changed, 490 insertions, 0 deletions
diff --git a/boost/beast/core/type_traits.hpp b/boost/beast/core/type_traits.hpp
new file mode 100644
index 0000000000..d622e0e8ec
--- /dev/null
+++ b/boost/beast/core/type_traits.hpp
@@ -0,0 +1,490 @@
+//
+// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/boostorg/beast
+//
+
+#ifndef BOOST_BEAST_TYPE_TRAITS_HPP
+#define BOOST_BEAST_TYPE_TRAITS_HPP
+
+#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/core/file_base.hpp>
+#include <boost/beast/core/detail/type_traits.hpp>
+#include <boost/asio/buffer.hpp>
+#include <type_traits>
+
+namespace boost {
+namespace beast {
+
+//------------------------------------------------------------------------------
+//
+// Handler concepts
+//
+//------------------------------------------------------------------------------
+
+/** Determine if `T` meets the requirements of @b CompletionHandler.
+
+ This trait checks whether a type meets the requirements for a completion
+ handler, and is also callable with the specified signature.
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` meets the requirements,
+ else the type will be `std::false_type`.
+
+ @par Example
+
+ Use with `static_assert`:
+
+ @code
+ struct handler
+ {
+ void operator()(error_code&);
+ };
+
+ static_assert(is_completion_handler<handler, void(error_code&)>::value,
+ "Not a completion handler");
+ @endcode
+*/
+template<class T, class Signature>
+#if BOOST_BEAST_DOXYGEN
+using is_completion_handler = std::integral_constant<bool, ...>;
+#else
+using is_completion_handler = std::integral_constant<bool,
+ std::is_copy_constructible<typename std::decay<T>::type>::value &&
+ detail::is_invocable<T, Signature>::value>;
+#endif
+
+//------------------------------------------------------------------------------
+//
+// Stream concepts
+//
+//------------------------------------------------------------------------------
+
+/** Determine if `T` has the `get_executor` member function.
+
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` has the member
+ function with the correct signature, else type will be `std::false_type`.
+
+ @par Example
+
+ Use with tag dispatching:
+
+ @code
+ template<class T>
+ void maybe_hello(T& t, std::true_type)
+ {
+ boost::asio::post(
+ t.get_executor(),
+ []
+ {
+ std::cout << "Hello, world!" << std::endl;
+ });
+ }
+
+ template<class T>
+ void maybe_hello(T&, std::false_type)
+ {
+ // T does not have get_executor
+ }
+
+ template<class T>
+ void maybe_hello(T& t)
+ {
+ maybe_hello(t, has_get_executor<T>{});
+ }
+ @endcode
+
+ Use with `static_assert`:
+
+ @code
+ struct stream
+ {
+ using executor_type = boost::asio::io_context::executor_type;
+ executor_type get_executor() noexcept;
+ };
+
+ static_assert(has_get_executor<stream>::value, "Missing get_executor member");
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct has_get_executor : std::integral_constant<bool, ...>{};
+#else
+template<class T, class = void>
+struct has_get_executor : std::false_type {};
+
+template<class T>
+struct has_get_executor<T, beast::detail::void_t<decltype(
+ std::declval<T&>().get_executor(),
+ (void)0)>> : std::true_type {};
+#endif
+
+/** Returns `T::lowest_layer_type` if it exists, else `T`
+
+ This will contain a nested `type` equal to `T::lowest_layer_type`
+ if it exists, else `type` will be equal to `T`.
+
+ @par Example
+
+ Declaring a wrapper:
+
+ @code
+ template<class Stream>
+ struct stream_wrapper
+ {
+ using next_layer_type = typename std::remove_reference<Stream>::type;
+ using lowest_layer_type = typename get_lowest_layer<stream_type>::type;
+ };
+ @endcode
+
+ Defining a metafunction:
+
+ @code
+ /// Alias for `std::true_type` if `T` wraps another stream
+ template<class T>
+ using is_stream_wrapper : std::integral_constant<bool,
+ ! std::is_same<T, typename get_lowest_layer<T>::type>::value> {};
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct get_lowest_layer;
+#else
+template<class T, class = void>
+struct get_lowest_layer
+{
+ using type = T;
+};
+
+template<class T>
+struct get_lowest_layer<T, detail::void_t<
+ typename T::lowest_layer_type>>
+{
+ using type = typename T::lowest_layer_type;
+};
+#endif
+
+/** Determine if `T` meets the requirements of @b AsyncReadStream.
+
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` meets the requirements,
+ else the type will be `std::false_type`.
+
+ @par Example
+
+ Use with `static_assert`:
+
+ @code
+ template<class AsyncReadStream>
+ void f(AsyncReadStream& stream)
+ {
+ static_assert(is_async_read_stream<AsyncReadStream>::value,
+ "AsyncReadStream requirements not met");
+ ...
+ @endcode
+
+ Use with `std::enable_if` (SFINAE):
+
+ @code
+ template<class AsyncReadStream>
+ typename std::enable_if<is_async_read_stream<AsyncReadStream>::value>::type
+ f(AsyncReadStream& stream);
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct is_async_read_stream : std::integral_constant<bool, ...>{};
+#else
+template<class T, class = void>
+struct is_async_read_stream : std::false_type {};
+
+template<class T>
+struct is_async_read_stream<T, detail::void_t<decltype(
+ std::declval<T>().async_read_some(
+ std::declval<detail::MutableBufferSequence>(),
+ std::declval<detail::ReadHandler>()),
+ (void)0)>> : std::integral_constant<bool,
+ has_get_executor<T>::value
+ > {};
+#endif
+
+/** Determine if `T` meets the requirements of @b AsyncWriteStream.
+
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` meets the requirements,
+ else the type will be `std::false_type`.
+
+ @par Example
+
+ Use with `static_assert`:
+
+ @code
+ template<class AsyncWriteStream>
+ void f(AsyncWriteStream& stream)
+ {
+ static_assert(is_async_write_stream<AsyncWriteStream>::value,
+ "AsyncWriteStream requirements not met");
+ ...
+ @endcode
+
+ Use with `std::enable_if` (SFINAE):
+
+ @code
+ template<class AsyncWriteStream>
+ typename std::enable_if<is_async_write_stream<AsyncWriteStream>::value>::type
+ f(AsyncWriteStream& stream);
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct is_async_write_stream : std::integral_constant<bool, ...>{};
+#else
+template<class T, class = void>
+struct is_async_write_stream : std::false_type {};
+
+template<class T>
+struct is_async_write_stream<T, detail::void_t<decltype(
+ std::declval<T>().async_write_some(
+ std::declval<detail::ConstBufferSequence>(),
+ std::declval<detail::WriteHandler>()),
+ (void)0)>> : std::integral_constant<bool,
+ has_get_executor<T>::value
+ > {};
+#endif
+
+/** Determine if `T` meets the requirements of @b SyncReadStream.
+
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` meets the requirements,
+ else the type will be `std::false_type`.
+
+ @par Example
+
+ Use with `static_assert`:
+
+ @code
+ template<class SyncReadStream>
+ void f(SyncReadStream& stream)
+ {
+ static_assert(is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream requirements not met");
+ ...
+ @endcode
+
+ Use with `std::enable_if` (SFINAE):
+
+ @code
+ template<class SyncReadStream>
+ typename std::enable_if<is_sync_read_stream<SyncReadStream>::value>::type
+ f(SyncReadStream& stream);
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct is_sync_read_stream : std::integral_constant<bool, ...>{};
+#else
+template<class T, class = void>
+struct is_sync_read_stream : std::false_type {};
+
+template<class T>
+struct is_sync_read_stream<T, detail::void_t<decltype(
+ std::declval<std::size_t&>() = std::declval<T>().read_some(
+ std::declval<detail::MutableBufferSequence>()),
+ std::declval<std::size_t&>() = std::declval<T>().read_some(
+ std::declval<detail::MutableBufferSequence>(),
+ std::declval<boost::system::error_code&>()),
+ (void)0)>> : std::true_type {};
+#endif
+
+/** Determine if `T` meets the requirements of @b SyncWriteStream.
+
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` meets the requirements,
+ else the type will be `std::false_type`.
+
+ @par Example
+
+ Use with `static_assert`:
+
+ @code
+ template<class SyncReadStream>
+ void f(SyncReadStream& stream)
+ {
+ static_assert(is_sync_read_stream<SyncReadStream>::value,
+ "SyncReadStream requirements not met");
+ ...
+ @endcode
+
+ Use with `std::enable_if` (SFINAE):
+
+ @code
+ template<class SyncReadStream>
+ typename std::enable_if<is_sync_read_stream<SyncReadStream>::value>::type
+ f(SyncReadStream& stream);
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct is_sync_write_stream : std::integral_constant<bool, ...>{};
+#else
+template<class T, class = void>
+struct is_sync_write_stream : std::false_type {};
+
+template<class T>
+struct is_sync_write_stream<T, detail::void_t<decltype(
+ std::declval<std::size_t&>() = std::declval<T&>().write_some(
+ std::declval<detail::ConstBufferSequence>()),
+ std::declval<std::size_t&>() = std::declval<T&>().write_some(
+ std::declval<detail::ConstBufferSequence>(),
+ std::declval<boost::system::error_code&>()),
+ (void)0)>> : std::true_type {};
+#endif
+
+/** Determine if `T` meets the requirements of @b AsyncStream.
+
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` meets the requirements,
+ else the type will be `std::false_type`.
+
+ @par Example
+
+ Use with `static_assert`:
+
+ @code
+ template<class AsyncStream>
+ void f(AsyncStream& stream)
+ {
+ static_assert(is_async_stream<AsyncStream>::value,
+ "AsyncStream requirements not met");
+ ...
+ @endcode
+
+ Use with `std::enable_if` (SFINAE):
+
+ @code
+ template<class AsyncStream>
+ typename std::enable_if<is_async_stream<AsyncStream>::value>::type
+ f(AsyncStream& stream);
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct is_async_stream : std::integral_constant<bool, ...>{};
+#else
+template<class T>
+using is_async_stream = std::integral_constant<bool,
+ is_async_read_stream<T>::value && is_async_write_stream<T>::value>;
+#endif
+
+/** Determine if `T` meets the requirements of @b SyncStream.
+
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` meets the requirements,
+ else the type will be `std::false_type`.
+
+ @par Example
+
+ Use with `static_assert`:
+
+ @code
+ template<class SyncStream>
+ void f(SyncStream& stream)
+ {
+ static_assert(is_sync_stream<SyncStream>::value,
+ "SyncStream requirements not met");
+ ...
+ @endcode
+
+ Use with `std::enable_if` (SFINAE):
+
+ @code
+ template<class SyncStream>
+ typename std::enable_if<is_sync_stream<SyncStream>::value>::type
+ f(SyncStream& stream);
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct is_sync_stream : std::integral_constant<bool, ...>{};
+#else
+template<class T>
+using is_sync_stream = std::integral_constant<bool,
+ is_sync_read_stream<T>::value && is_sync_write_stream<T>::value>;
+#endif
+
+//------------------------------------------------------------------------------
+//
+// File concepts
+//
+//------------------------------------------------------------------------------
+
+/** Determine if `T` meets the requirements of @b File.
+
+ Metafunctions are used to perform compile time checking of template
+ types. This type will be `std::true_type` if `T` meets the requirements,
+ else the type will be `std::false_type`.
+
+ @par Example
+
+ Use with `static_assert`:
+
+ @code
+ template<class File>
+ void f(File& file)
+ {
+ static_assert(is_file<File>::value,
+ "File requirements not met");
+ ...
+ @endcode
+
+ Use with `std::enable_if` (SFINAE):
+
+ @code
+ template<class File>
+ typename std::enable_if<is_file<File>::value>::type
+ f(File& file);
+ @endcode
+*/
+#if BOOST_BEAST_DOXYGEN
+template<class T>
+struct is_file : std::integral_constant<bool, ...>{};
+#else
+template<class T, class = void>
+struct is_file : std::false_type {};
+
+template<class T>
+struct is_file<T, detail::void_t<decltype(
+ std::declval<bool&>() = std::declval<T const&>().is_open(),
+ std::declval<T&>().close(std::declval<error_code&>()),
+ std::declval<T&>().open(
+ std::declval<char const*>(),
+ std::declval<file_mode>(),
+ std::declval<error_code&>()),
+ std::declval<std::uint64_t&>() = std::declval<T&>().size(
+ std::declval<error_code&>()),
+ std::declval<std::uint64_t&>() = std::declval<T&>().pos(
+ std::declval<error_code&>()),
+ std::declval<T&>().seek(
+ std::declval<std::uint64_t>(),
+ std::declval<error_code&>()),
+ std::declval<std::size_t&>() = std::declval<T&>().read(
+ std::declval<void*>(),
+ std::declval<std::size_t>(),
+ std::declval<error_code&>()),
+ std::declval<std::size_t&>() = std::declval<T&>().write(
+ std::declval<void const*>(),
+ std::declval<std::size_t>(),
+ std::declval<error_code&>()),
+ (void)0)>> : std::integral_constant<bool,
+ std::is_default_constructible<T>::value &&
+ std::is_destructible<T>::value
+ > {};
+#endif
+
+} // beast
+} // boost
+
+#endif