为什么模板不丢弃 co_return?
Why does template not discard the co_return?
我想创建一个同时具有同步和协程版本的函数,而不使用模板专业化,即 if constexpr
。
这是我写的函数:
template <Async _a>
AsyncResult<int, _a> func(int a) {
if constexpr (_a == Async::Disable)
return a;
else
co_return a;
}
但是当我实例化真正的分支时它给出了一个错误
auto a = func<Async::Disable>(1); // compiler error
auto b = func<Async::Enable>(2); // ok
error: unable to find the promise type for this coroutine
为什么这不起作用?
标准明确表示这是不可能的。根据 stmt.return.coroutine#1
中的注释 1
... A coroutine shall not enclose a return statement ([stmt.return]).
[Note 1: For this determination, it is irrelevant whether the return statement is enclosed by a discarded statement ([stmt.if]). — end note]
因此您将无法 return 从协程中,即使它在丢弃的语句中。您可以专门化函数模板而不是使用 if constexpr
.
template <Async _a>
AsyncResult<int, _a> func(int a)
{
co_return a;
}
template <>
AsyncResult<int, Async::Disable> func<Async::Disable>(int a)
{
return a;
}
这里是 demo。
其中包含 co_return
/co_await
/co_yield
语句的函数无条件是协程,即使它被 if constexpr
.[=18 丢弃也是如此=]
您将必须拥有 2 个不同的功能。以下是您可以做的一些事情:
// Have the second function be a lambda:
template <Async _a>
AsyncResult<int, _a> func(int a) {
if constexpr (_a == Async::Disable)
return a;
else
return ([](int a) -> AsyncResult<int, _a> {
co_return a;
})(a);
}
// Have the second function be a helper function
namespace detail {
AsyncResult<int, Async::Enable> async_enable_func(int a) {
co_return a;
}
}
template <Async _a>
AsyncResult<int, _a> func(int a) {
if constexpr (_a == Async::Disable)
return a;
else
return detail::async_enable_func(a);
}
// Have the second function be an overload
template <Async _a> requires (_a == Async::Disable)
AsyncResult<int, _a> func(int a) {
return a;
}
template <Async _a> requires (_a == Async::Enable)
AsyncResult<int, _a> func(int a) {
co_return a;
}
// Since you only have 1 template parameter, you can fully specialize
template<Async _a>
AsyncResult<int, _a> func(int a) {
return a;
}
template<>
AsyncResult<int, Async::Enable> func<Async::Enable>(int a) {
co_return a;
}
我想创建一个同时具有同步和协程版本的函数,而不使用模板专业化,即 if constexpr
。
这是我写的函数:
template <Async _a>
AsyncResult<int, _a> func(int a) {
if constexpr (_a == Async::Disable)
return a;
else
co_return a;
}
但是当我实例化真正的分支时它给出了一个错误
auto a = func<Async::Disable>(1); // compiler error
auto b = func<Async::Enable>(2); // ok
error: unable to find the promise type for this coroutine
为什么这不起作用?
标准明确表示这是不可能的。根据 stmt.return.coroutine#1
中的注释 1... A coroutine shall not enclose a return statement ([stmt.return]).
[Note 1: For this determination, it is irrelevant whether the return statement is enclosed by a discarded statement ([stmt.if]). — end note]
因此您将无法 return 从协程中,即使它在丢弃的语句中。您可以专门化函数模板而不是使用 if constexpr
.
template <Async _a>
AsyncResult<int, _a> func(int a)
{
co_return a;
}
template <>
AsyncResult<int, Async::Disable> func<Async::Disable>(int a)
{
return a;
}
这里是 demo。
其中包含 co_return
/co_await
/co_yield
语句的函数无条件是协程,即使它被 if constexpr
.[=18 丢弃也是如此=]
您将必须拥有 2 个不同的功能。以下是您可以做的一些事情:
// Have the second function be a lambda:
template <Async _a>
AsyncResult<int, _a> func(int a) {
if constexpr (_a == Async::Disable)
return a;
else
return ([](int a) -> AsyncResult<int, _a> {
co_return a;
})(a);
}
// Have the second function be a helper function
namespace detail {
AsyncResult<int, Async::Enable> async_enable_func(int a) {
co_return a;
}
}
template <Async _a>
AsyncResult<int, _a> func(int a) {
if constexpr (_a == Async::Disable)
return a;
else
return detail::async_enable_func(a);
}
// Have the second function be an overload
template <Async _a> requires (_a == Async::Disable)
AsyncResult<int, _a> func(int a) {
return a;
}
template <Async _a> requires (_a == Async::Enable)
AsyncResult<int, _a> func(int a) {
co_return a;
}
// Since you only have 1 template parameter, you can fully specialize
template<Async _a>
AsyncResult<int, _a> func(int a) {
return a;
}
template<>
AsyncResult<int, Async::Enable> func<Async::Enable>(int a) {
co_return a;
}