1 //  { dg-additional-options "-std=c++20 -fpreprocessed -w" }
2 namespace std {
3 inline namespace {
4 template <typename _Result, typename> struct coroutine_traits {
5   using promise_type = _Result::promise_type;
6 };
7 template <typename = void> struct coroutine_handle;
8 template <> struct coroutine_handle<> { public: };
9 template <typename> struct coroutine_handle : coroutine_handle<> {};
10 struct suspend_always {
11   bool await_ready();
12   void await_suspend(coroutine_handle<>);
13   void await_resume();
14 };
15 } // namespace
16 } // namespace std
17 namespace coro = std;
18 namespace cppcoro {
19 class task {
20 private:
21   struct awaitable_base {
22     coro::coroutine_handle<> m_coroutine;
23     bool await_ready() const noexcept;
24     void await_suspend(coro::coroutine_handle<> awaitingCoroutine) noexcept;
25   };
26 
27 public:
28   auto operator co_await() const &noexcept {
29     struct awaitable : awaitable_base {
30       decltype(auto) await_resume() {}
31     };
32     return awaitable{m_coroutine};
33   }
34 
35 private:
36   coro::coroutine_handle<> m_coroutine;
37 };
38 class shared_task;
39 class shared_task_promise_base {
40   struct final_awaiter {
41     bool await_ready() const noexcept;
42     template <typename PROMISE>
43     void await_suspend(coro::coroutine_handle<PROMISE> h) noexcept;
44     void await_resume() noexcept;
45   };
46 
47 public:
48   coro::suspend_always initial_suspend() noexcept;
49   final_awaiter final_suspend() noexcept;
50   void unhandled_exception() noexcept;
51 };
52 class shared_task_promise : public shared_task_promise_base {
53 public:
54   shared_task get_return_object() noexcept;
55   void return_void() noexcept;
56 };
57 class shared_task {
58 public:
59   using promise_type = shared_task_promise;
60 };
61 auto make_shared_task(cppcoro::task awaitable) -> shared_task {
62   co_return co_await static_cast<cppcoro::task &&>(awaitable);
63 }
64 } // namespace cppcoro
65