1//
2// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
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
8#ifndef BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP
9#define BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP
10
11#include <boost/cobalt/concepts.hpp>
12#include <utility>
13
14namespace boost::cobalt::detail
15{
16
17template<awaitable_type T>
18auto co_await_result_helper() -> decltype(std::declval<T&>());
19
20template<typename T>
21auto co_await_result_helper() -> decltype(std::declval<T>().operator co_await());
22
23template<typename T>
24auto co_await_result_helper() -> decltype(operator co_await(std::declval<T>()));
25
26template<typename T>
27using co_awaitable_type = decltype(co_await_result_helper<T>());
28
29template<typename T>
30using co_await_result_t = decltype(co_await_result_helper<T>().await_resume());
31
32template<awaitable_type T>
33T&& get_awaitable_type(T && t) { return std::forward<T>(t);}
34
35template<typename T>
36 requires (requires (T && t) {{operator co_await(std::forward<T>(t))} -> awaitable_type;} )
37decltype(auto) get_awaitable_type(T && t) { return operator co_await(std::forward<T>(t));}
38
39template<typename T>
40requires (requires (T && t) {{std::forward<T>(t).operator co_await()} -> awaitable_type;} )
41decltype(auto) get_awaitable_type(T && t) { return std::forward<T>(t).operator co_await();}
42
43template<typename T>
44struct awaitable_type_getter
45{
46 using type = co_awaitable_type<T&&>;
47 std::decay_t<T> & ref;
48
49 template<typename U>
50 awaitable_type_getter(U && ref) : ref(ref) {}
51
52 operator type ()
53 {
54 if constexpr (std::is_lvalue_reference_v<T>)
55 return get_awaitable_type(ref);
56 else
57 return get_awaitable_type(std::move(ref));
58 }
59};
60
61
62template<awaitable_type T>
63 struct awaitable_type_getter<T>
64{
65 using type = T&&;
66 std::decay_t<T> & ref;
67
68 template<typename U>
69 awaitable_type_getter(U && ref) : ref(ref) {}
70
71 operator type ()
72 {
73 if constexpr (std::is_lvalue_reference_v<T>)
74 return ref;
75 else
76 return std::move(ref);
77 }
78};
79
80}
81
82#endif //BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP
83

source code of boost/libs/cobalt/include/boost/cobalt/detail/await_result_helper.hpp