await_result_helper.hpp 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. #ifndef BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP
  8. #define BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP
  9. #include <boost/cobalt/concepts.hpp>
  10. #include <utility>
  11. namespace boost::cobalt::detail
  12. {
  13. template<awaitable_type T>
  14. auto co_await_result_helper() -> decltype(std::declval<T&>());
  15. template<typename T>
  16. auto co_await_result_helper() -> decltype(std::declval<T>().operator co_await());
  17. template<typename T>
  18. auto co_await_result_helper() -> decltype(operator co_await(std::declval<T>()));
  19. template<typename T>
  20. using co_awaitable_type = decltype(co_await_result_helper<T>());
  21. template<typename T>
  22. using co_await_result_t = decltype(co_await_result_helper<T>().await_resume());
  23. template<awaitable_type T>
  24. T&& get_awaitable_type(T && t) { return std::forward<T>(t);}
  25. template<typename T>
  26. requires (requires (T && t) {{operator co_await(std::forward<T>(t))} -> awaitable_type;} )
  27. decltype(auto) get_awaitable_type(T && t) { return operator co_await(std::forward<T>(t));}
  28. template<typename T>
  29. requires (requires (T && t) {{std::forward<T>(t).operator co_await()} -> awaitable_type;} )
  30. decltype(auto) get_awaitable_type(T && t) { return std::forward<T>(t).operator co_await();}
  31. template<typename T>
  32. struct awaitable_type_getter
  33. {
  34. using type = co_awaitable_type<T&&>;
  35. std::decay_t<T> & ref;
  36. template<typename U>
  37. awaitable_type_getter(U && ref) : ref(ref) {}
  38. operator type ()
  39. {
  40. if constexpr (std::is_lvalue_reference_v<T>)
  41. return get_awaitable_type(ref);
  42. else
  43. return get_awaitable_type(std::move(ref));
  44. }
  45. };
  46. template<awaitable_type T>
  47. struct awaitable_type_getter<T>
  48. {
  49. using type = T&&;
  50. std::decay_t<T> & ref;
  51. template<typename U>
  52. awaitable_type_getter(U && ref) : ref(ref) {}
  53. operator type ()
  54. {
  55. if constexpr (std::is_lvalue_reference_v<T>)
  56. return ref;
  57. else
  58. return std::move(ref);
  59. }
  60. };
  61. }
  62. #endif //BOOST_COBALT_DETAIL_AWAIT_RESULT_HELPER_HPP