async_mqtt 5.0.0
Loading...
Searching...
No Matches
stream_traits.hpp
1// Copyright Takatoshi Kondo 2022
2//
3// Distributed under the Boost Software License, Version 1.0.
4// (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7#if !defined(ASYNC_MQTT_STREAM_TRAITS_HPP)
8#define ASYNC_MQTT_STREAM_TRAITS_HPP
9
10#include <type_traits>
11
12namespace async_mqtt {
13
14namespace detail {
15
16template <typename T>
17std::false_type has_next_layer_impl(void*);
18
19template <typename T>
20auto has_next_layer_impl(decltype(nullptr)) ->
21 decltype(std::declval<T&>().next_layer(), std::true_type{});
22
23template <typename T>
24using has_next_layer = decltype(has_next_layer_impl<T>(nullptr));
25
26template<typename T, bool = has_next_layer<T>::value>
27struct lowest_layer_type_impl {
28 using type = typename std::remove_reference<T>::type;
29};
30
31template<typename T>
32struct lowest_layer_type_impl<T, true> {
33 using type = typename lowest_layer_type_impl<
34 decltype(std::declval<T&>().next_layer())>::type;
35};
36
37template<typename T>
38using lowest_layer_type = typename lowest_layer_type_impl<T>::type;
39
40template<typename T>
41T&
42get_lowest_layer_impl(T& t, std::false_type) noexcept {
43 return t;
44}
45
46template<typename T>
47lowest_layer_type<T>&
48get_lowest_layer_impl(T& t, std::true_type) noexcept {
49 return
50 get_lowest_layer_impl(
51 t.next_layer(),
52 has_next_layer<typename std::decay<decltype(t.next_layer())>::type>{}
53 );
54}
55
56} // namespace detail
57
58template<typename T>
59using executor_type = decltype(std::declval<T>().get_executor());
60
61template<typename T>
62using lowest_layer_type = detail::lowest_layer_type<T>;
63
64template<typename T>
65lowest_layer_type<T>& get_lowest_layer(T& t) noexcept {
66 return
67 detail::get_lowest_layer_impl(
68 t,
69 detail::has_next_layer<T>{}
70 );
71}
72
73
74} // namespace async_mqtt
75
76#endif // ASYNC_MQTT_STREAM_TRAITS_HPP