File return.h

File List > coroutine > return.h

Go to the documentation of this file.

#pragma once
#ifndef COROUTINE_PROMISE_AND_RETURN_TYPES_H
#define COROUTINE_PROMISE_AND_RETURN_TYPES_H
#include <type_traits>

#if __has_include(<coroutine/frame.h>) && !defined(USE_EXPERIMENTAL_COROUTINE)
#include <coroutine/frame.h>

namespace coro {
using std::coroutine_handle;
using std::suspend_always;
using std::suspend_never;

#elif __has_include(<experimental/coroutine>)
#include <experimental/coroutine>

namespace coro {
using std::experimental::coroutine_handle;
using std::experimental::suspend_always;
using std::experimental::suspend_never;

#else
#error "requires header <experimental/coroutine> or <coroutine/frame.h>"
#endif // <experimental/coroutine>

class promise_nn {
  public:
    suspend_never initial_suspend() noexcept {
        return {};
    }
    suspend_never final_suspend() noexcept {
        return {};
    }
};

class promise_na {
  public:
    suspend_never initial_suspend() noexcept {
        return {};
    }
    suspend_always final_suspend() noexcept {
        return {};
    }
};

class promise_an {
  public:
    suspend_always initial_suspend() noexcept {
        return {};
    }
    suspend_never final_suspend() noexcept {
        return {};
    }
};

class promise_aa {
  public:
    suspend_always initial_suspend() noexcept {
        return {};
    }
    suspend_always final_suspend() noexcept {
        return {};
    }
};

class null_frame_promise : public promise_nn {
  public:
    void unhandled_exception() noexcept(false) {
        throw;
    }
    void return_void() noexcept {
    }
};

struct null_frame_t final {
    struct promise_type : public null_frame_promise {
        null_frame_t get_return_object() noexcept {
            return {};
        }
    };
};

class frame_t : public coroutine_handle<void> {
  public:
    class promise_type : public promise_na {
      public:
        void unhandled_exception() noexcept(false) {
            throw;
        }
        void return_void() noexcept {
        }
        frame_t get_return_object() noexcept {
            return frame_t{coroutine_handle<promise_type>::from_promise(*this)};
        }
    };

  public:
    explicit frame_t(coroutine_handle<void> frame = nullptr) noexcept
        : coroutine_handle<void>{frame} {
    }
};

class passive_frame_t : public coroutine_handle<void> {
  public:
    class promise_type : public promise_aa {
      public:
        void unhandled_exception() noexcept(false) {
            throw;
        }
        void return_void() noexcept {
        }
        passive_frame_t get_return_object() noexcept {
            return passive_frame_t{
                coroutine_handle<promise_type>::from_promise(*this)};
        }
    };
    explicit passive_frame_t(coroutine_handle<void> frame = nullptr) noexcept
        : coroutine_handle<void>{frame} {
    }
};

#if defined(__cpp_concepts)
/*
template <typename T, typename R = void>
concept awaitable = requires(T a, coroutine_handle<void> h) {
    { a.await_ready() } ->bool;
    { a.await_suspend(h) } ->void;
    { a.await_resume() } ->R;
};
template <typename P>
concept promise_requirement_basic = requires(P p) {
    { p.initial_suspend() } ->awaitable;
    { p.final_suspend() } ->awaitable;
    { p.unhandled_exception() } ->void;
};
*/
#endif

} // namespace coro

namespace std {
namespace experimental {

template <typename... P>
struct coroutine_traits<nullptr_t, P...> {
    struct promise_type : public coro::null_frame_promise {
        nullptr_t get_return_object() noexcept {
            return nullptr;
        }
    };
};

} // namespace experimental
} // namespace std

#endif // COROUTINE_PROMISE_AND_RETURN_TYPES_H