From 1f946bff502988cdf88ee16070cd5ec602b4e7fa Mon Sep 17 00:00:00 2001 From: q66 Date: Sun, 5 Mar 2017 23:48:51 +0100 Subject: [PATCH] forwarding of coroutine args/results --- ostd/coroutine.hh | 74 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/ostd/coroutine.hh b/ostd/coroutine.hh index 4b5f425..8a02810 100644 --- a/ostd/coroutine.hh +++ b/ostd/coroutine.hh @@ -13,6 +13,7 @@ #include #include #include +#include #include "ostd/types.hh" #include "ostd/platform.hh" @@ -136,19 +137,68 @@ template struct coroutine; namespace detail { + /* like reference_wrapper but for any value */ + template + struct arg_wrapper { + arg_wrapper() = default; + arg_wrapper(T arg): p_arg(std::move(arg)) {} + + void operator=(T arg) { + p_arg = std::move(arg); + } + operator T &&() { + return std::move(p_arg); + } + + private: + T p_arg = T{}; + }; + + template + struct arg_wrapper { + arg_wrapper() = default; + arg_wrapper(T &&arg): p_arg(&arg) {} + + void operator=(T &&arg) { + p_arg = &arg; + } + operator T &&() { + return *p_arg; + } + + private: + T *p_arg = nullptr; + }; + + template + struct arg_wrapper { + arg_wrapper() = default; + arg_wrapper(T &arg): p_arg(&arg) {} + + void operator=(T &arg) { + p_arg = &arg; + } + operator T &() { + return *p_arg; + } + + private: + T *p_arg = nullptr; + }; + template struct coro_types { - using yield_type = std::tuple; + using yield_type = std::tuple; }; template struct coro_types { - using yield_type = A &&; + using yield_type = A; }; template struct coro_types { - using yield_type = std::pair; + using yield_type = std::pair; }; template @@ -156,10 +206,10 @@ namespace detail { template inline coro_args yield_ret( - std::tuple &args, std::index_sequence + std::tuple...> &args, std::index_sequence ) { if constexpr(sizeof...(A) == 1) { - return std::move(std::get<0>(args)); + return std::forward(std::get<0>(args)); } else if constexpr(sizeof...(A) == 2) { return std::make_pair(std::forward(std::get(args))...); } else { @@ -189,13 +239,13 @@ namespace detail { } R call(A ...args) { - p_args = std::forward_as_tuple(std::forward(args)...); + p_args = std::make_tuple(arg_wrapper(std::forward(args))...); p_ctx.call(); - return std::forward(this->p_result); + return std::forward(p_result); } - std::tuple p_args; - R p_result; + std::tuple...> p_args; + arg_wrapper p_result; coroutine_context p_ctx; }; @@ -222,7 +272,7 @@ namespace detail { return std::forward(this->p_result); } - R p_result; + arg_wrapper p_result; coroutine_context p_ctx; }; @@ -245,11 +295,11 @@ namespace detail { } void call(A ...args) { - p_args = std::forward_as_tuple(std::forward(args)...); + p_args = std::make_tuple(arg_wrapper(std::forward(args))...); p_ctx.call(); } - std::tuple p_args; + std::tuple...> p_args; coroutine_context p_ctx; };