// // Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net) // // 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) // #ifndef BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP #define BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP #include #include namespace boost::cobalt::detail { template auto co_await_result_helper() -> decltype(std::declval()); template auto co_await_result_helper() -> decltype(std::declval().operator co_await()); template auto co_await_result_helper() -> decltype(operator co_await(std::declval())); template using co_awaitable_type = decltype(co_await_result_helper()); template using co_await_result_t = decltype(co_await_result_helper().await_resume()); template T&& get_awaitable_type(T && t) { return std::forward(t);} template requires (requires (T && t) {{operator co_await(std::forward(t))} -> awaitable_type;} ) decltype(auto) get_awaitable_type(T && t) { return operator co_await(std::forward(t));} template requires (requires (T && t) {{std::forward(t).operator co_await()} -> awaitable_type;} ) decltype(auto) get_awaitable_type(T && t) { return std::forward(t).operator co_await();} template struct awaitable_type_getter { using type = co_awaitable_type; std::decay_t & ref; template awaitable_type_getter(U && ref) : ref(ref) {} operator type () { if constexpr (std::is_lvalue_reference_v) return get_awaitable_type(ref); else return get_awaitable_type(std::move(ref)); } }; template struct awaitable_type_getter { using type = T&&; std::decay_t & ref; template awaitable_type_getter(U && ref) : ref(ref) {} operator type () { if constexpr (std::is_lvalue_reference_v) return ref; else return std::move(ref); } }; } #endif //BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP