// Copyright (c) 2022 Klemens D. Morgenstern // // 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_UTIL_HPP #define BOOST_COBALT_UTIL_HPP #include #include #include #include #include #include #include #include namespace boost::variant2 { struct monostate; } namespace boost::cobalt::detail { template constexpr std::size_t variadic_first(std::size_t = 0u) { return std::numeric_limits::max(); } template constexpr std::size_t variadic_first(std::size_t pos = 0u) { if constexpr (std::is_same_v, T>) return pos; else return variadic_first(pos+1); } template constexpr bool variadic_has = variadic_first() < sizeof...(Args); template requires (Idx <= sizeof...(Args)) constexpr decltype(auto) get_variadic(First && first, Args && ... args) { if constexpr (Idx == 0u) return static_cast(first); else return get_variadic(static_cast(args)...); } template struct variadic_element; template struct variadic_element { using type = typename variadic_element::type; }; template struct variadic_element<0u, First, Tail...> { using type = First; }; template using variadic_element_t = typename variadic_element::type; template struct variadic_last { using type = variadic_element_t; }; template<> struct variadic_last<> { using type = void; }; template using variadic_last_t = typename variadic_last::type; template constexpr decltype(auto) get_last_variadic(First && first) { return first; } template constexpr decltype(auto) get_last_variadic(First &&, Args && ... args) { return get_last_variadic(static_cast(args)...); } template auto get_resume_result(Awaitable & aw) -> system::result { using type = decltype(aw.await_resume()); BOOST_TRY { if constexpr (std::is_void_v) { aw.await_resume(); return {}; } else return aw.await_resume(); } BOOST_CATCH(...) { return std::current_exception(); } BOOST_CATCH_END } #if BOOST_COBALT_NO_SELF_DELETE BOOST_COBALT_DECL void self_destroy(std::coroutine_handle h, const cobalt::executor & exec) noexcept; template inline void self_destroy(std::coroutine_handle h) noexcept { if constexpr (requires {h.promise().get_executor();}) self_destroy(h, h.promise().get_executor()); else self_destroy(h, this_thread::get_executor()); } #else template inline void self_destroy(std::coroutine_handle h) noexcept { h.destroy(); } template inline void self_destroy(std::coroutine_handle h, const Executor &) noexcept { h.destroy(); } #endif template using void_as_monostate = std::conditional_t, variant2::monostate, T>; template using monostate_as_void = std::conditional_t, void, T>; } #endif //BOOST_COBALT_UTIL_HPP