summaryrefslogtreecommitdiff
path: root/boost/beast/core/detail/type_traits.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/core/detail/type_traits.hpp')
-rw-r--r--boost/beast/core/detail/type_traits.hpp353
1 files changed, 353 insertions, 0 deletions
diff --git a/boost/beast/core/detail/type_traits.hpp b/boost/beast/core/detail/type_traits.hpp
new file mode 100644
index 0000000000..06fbda291d
--- /dev/null
+++ b/boost/beast/core/detail/type_traits.hpp
@@ -0,0 +1,353 @@
+//
+// 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_DETAIL_TYPE_TRAITS_HPP
+#define BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP
+
+#include <boost/beast/core/error.hpp>
+#include <boost/asio/buffer.hpp>
+#include <iterator>
+#include <tuple>
+#include <type_traits>
+#include <string>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+//
+// utilities
+//
+
+template<class... Ts>
+struct make_void
+{
+ using type = void;
+};
+
+template<class... Ts>
+using void_t = typename make_void<Ts...>::type;
+
+template<class T>
+inline
+void
+accept_rv(T){}
+
+template<class U>
+std::size_t constexpr
+max_sizeof()
+{
+ return sizeof(U);
+}
+
+template<class U0, class U1, class... Us>
+std::size_t constexpr
+max_sizeof()
+{
+ return
+ max_sizeof<U0>() > max_sizeof<U1, Us...>() ?
+ max_sizeof<U0>() : max_sizeof<U1, Us...>();
+}
+
+template<class U>
+std::size_t constexpr
+max_alignof()
+{
+ return alignof(U);
+}
+
+template<class U0, class U1, class... Us>
+std::size_t constexpr
+max_alignof()
+{
+ return
+ max_alignof<U0>() > max_alignof<U1, Us...>() ?
+ max_alignof<U0>() : max_alignof<U1, Us...>();
+}
+
+template<unsigned N, class T, class... Tn>
+struct repeat_tuple_impl
+{
+ using type = typename repeat_tuple_impl<
+ N - 1, T, T, Tn...>::type;
+};
+
+template<class T, class... Tn>
+struct repeat_tuple_impl<0, T, Tn...>
+{
+ using type = std::tuple<T, Tn...>;
+};
+
+template<unsigned N, class T>
+struct repeat_tuple
+{
+ using type =
+ typename repeat_tuple_impl<N-1, T>::type;
+};
+
+template<class T>
+struct repeat_tuple<0, T>
+{
+ using type = std::tuple<>;
+};
+
+template<class R, class C, class ...A>
+auto
+is_invocable_test(C&& c, int, A&& ...a)
+ -> decltype(std::is_convertible<
+ decltype(c(std::forward<A>(a)...)), R>::value ||
+ std::is_same<R, void>::value,
+ std::true_type());
+
+template<class R, class C, class ...A>
+std::false_type
+is_invocable_test(C&& c, long, A&& ...a);
+
+/** Metafunction returns `true` if F callable as R(A...)
+
+ Example:
+
+ @code
+ is_invocable<T, void(std::string)>
+ @endcode
+*/
+/** @{ */
+template<class C, class F>
+struct is_invocable : std::false_type
+{
+};
+
+template<class C, class R, class ...A>
+struct is_invocable<C, R(A...)>
+ : decltype(is_invocable_test<R>(
+ std::declval<C>(), 1, std::declval<A>()...))
+{
+};
+/** @} */
+
+// for span
+template<class T, class E, class = void>
+struct is_contiguous_container: std::false_type {};
+
+template<class T, class E>
+struct is_contiguous_container<T, E, void_t<
+ decltype(
+ std::declval<std::size_t&>() = std::declval<T const&>().size(),
+ std::declval<E*&>() = std::declval<T&>().data(),
+ (void)0),
+ typename std::enable_if<
+ std::is_same<
+ typename std::remove_cv<E>::type,
+ typename std::remove_cv<
+ typename std::remove_pointer<
+ decltype(std::declval<T&>().data())
+ >::type
+ >::type
+ >::value
+ >::type>>: std::true_type
+{};
+
+template<class...>
+struct unwidest_unsigned;
+
+template<class U0>
+struct unwidest_unsigned<U0>
+{
+ using type = U0;
+};
+
+template<class U0, class... UN>
+struct unwidest_unsigned<U0, UN...>
+{
+ BOOST_STATIC_ASSERT(std::is_unsigned<U0>::value);
+ using type = typename std::conditional<
+ (sizeof(U0) < sizeof(typename unwidest_unsigned<UN...>::type)),
+ U0, typename unwidest_unsigned<UN...>::type>::type;
+};
+
+template<class...>
+struct widest_unsigned;
+
+template<class U0>
+struct widest_unsigned<U0>
+{
+ using type = U0;
+};
+
+template<class U0, class... UN>
+struct widest_unsigned<U0, UN...>
+{
+ BOOST_STATIC_ASSERT(std::is_unsigned<U0>::value);
+ using type = typename std::conditional<
+ (sizeof(U0) > sizeof(typename widest_unsigned<UN...>::type)),
+ U0, typename widest_unsigned<UN...>::type>::type;
+};
+
+template<class U>
+inline
+constexpr
+U
+min_all(U u)
+{
+ BOOST_STATIC_ASSERT(std::is_unsigned<U>::value);
+ return u;
+}
+
+template<class U0, class U1, class... UN>
+inline
+constexpr
+typename unwidest_unsigned<U0, U1, UN...>::type
+min_all(U0 u0, U1 u1, UN... un)
+{
+ using type =
+ typename unwidest_unsigned<U0, U1, UN...>::type;
+ return u0 < u1 ?
+ static_cast<type>(min_all(u0, un...)) :
+ static_cast<type>(min_all(u1, un...));
+}
+
+template<class U>
+inline
+constexpr
+U
+max_all(U u)
+{
+ BOOST_STATIC_ASSERT(std::is_unsigned<U>::value);
+ return u;
+}
+
+template<class U0, class U1, class... UN>
+inline
+constexpr
+typename widest_unsigned<U0, U1, UN...>::type
+max_all(U0 u0, U1 u1, UN... un)
+{
+ return u0 > u1? max_all(u0, un...) : max_all(u1, un...);
+}
+
+//------------------------------------------------------------------------------
+
+//
+// buffer concepts
+//
+
+// Types that meet the requirements,
+// for use with std::declval only.
+template<class BufferType>
+struct BufferSequence
+{
+ using value_type = BufferType;
+ using const_iterator = BufferType const*;
+ ~BufferSequence();
+ BufferSequence(BufferSequence const&) = default;
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+};
+using ConstBufferSequence =
+ BufferSequence<boost::asio::const_buffer>;
+using MutableBufferSequence =
+ BufferSequence<boost::asio::mutable_buffer>;
+
+template<class B1, class... Bn>
+struct is_all_const_buffer_sequence
+ : std::integral_constant<bool,
+ boost::asio::is_const_buffer_sequence<B1>::value &&
+ is_all_const_buffer_sequence<Bn...>::value>
+{
+};
+
+template<class B>
+struct is_all_const_buffer_sequence<B>
+ : boost::asio::is_const_buffer_sequence<B>
+{
+};
+
+template<class... Bn>
+struct common_buffers_type
+{
+ using type = typename std::conditional<
+ std::is_convertible<std::tuple<Bn...>,
+ typename repeat_tuple<sizeof...(Bn),
+ boost::asio::mutable_buffer>::type>::value,
+ boost::asio::mutable_buffer,
+ boost::asio::const_buffer>::type;
+};
+
+template<class B>
+struct buffer_sequence_iterator
+{
+ using type = decltype(
+ boost::asio::buffer_sequence_begin(
+ std::declval<B const&>()));
+};
+
+// Types that meet the requirements,
+// for use with std::declval only.
+struct StreamHandler
+{
+ StreamHandler(StreamHandler const&) = default;
+ void operator()(error_code ec, std::size_t);
+};
+using ReadHandler = StreamHandler;
+using WriteHandler = StreamHandler;
+
+template<class Buffers>
+class buffers_range_adapter
+{
+ Buffers const& b_;
+
+public:
+ using value_type = typename std::conditional<
+ std::is_convertible<typename std::iterator_traits<
+ typename buffer_sequence_iterator<Buffers>::type>::value_type,
+ boost::asio::const_buffer>::value,
+ boost::asio::const_buffer,
+ boost::asio::mutable_buffer>::type;
+
+ /* VFALCO This isn't right, because range-for will pick up the iterator's
+ value_type which might not be const_buffer or mutable_buffer. We
+ need to declare our own iterator wrapper that converts the underlying
+ iterator's value_type to const_buffer or mutable_buffer so that
+ range-for sees one of those types.
+ */
+ using const_iterator = typename
+ buffer_sequence_iterator<Buffers>::type;
+
+ explicit
+ buffers_range_adapter(Buffers const& b)
+ : b_(b)
+ {
+ }
+
+ const_iterator
+ begin() const noexcept
+ {
+ return boost::asio::buffer_sequence_begin(b_);
+ }
+
+ const_iterator
+ end() const noexcept
+ {
+ return boost::asio::buffer_sequence_end(b_);
+ }
+};
+
+template<class Buffers>
+buffers_range_adapter<Buffers>
+buffers_range(Buffers const& buffers)
+{
+ return buffers_range_adapter<Buffers>{buffers};
+}
+
+} // detail
+} // beast
+} // boost
+
+#endif