在支持 lambda 的同时约束 ClassType 的 coroutine_traits

问题描述 投票:0回答:1

我目前正在编写一个与 co_await 一起使用的协程/promise 库,当有不相关的 lambda 返回任务类型时,我很难约束成员函数

coroutine_traits
在 Godbolt 上重现问题的示例

#include <type_traits> #include <coroutine> #include <future> template<typename T> class TaskType { }; class SomeSafeClassA {}; class SomeSafeClassB {}; template<typename T> concept IsSafeClassA = std::is_base_of_v<SomeSafeClassA, T>; template<typename T> concept IsSafeClassB = std::is_base_of_v<SomeSafeClassB, T>; namespace std { template<typename... Args> struct coroutine_traits<TaskType<int>, Args...>{ using promise_type = TaskType<int>; }; template<IsSafeClassA ClassType, typename... Args> struct coroutine_traits<TaskType<int>, ClassType&, Args...>{ using promise_type = TaskType<int>; }; template<IsSafeClassB ClassType, typename... Args> struct coroutine_traits<TaskType<int>, ClassType&, Args...>{ using promise_type = TaskType<int>; }; } int main() { auto k = []() -> TaskType<int> { co_return 6; }; }

现在显然 TaskType 在这里还没有完全实现(它是在真实版本中)。问题是这个编译错误:
.../type_traits:3514:60: error: incomplete type 'const (lambda at <source>:38:14)' used in type trait expression
 3514 |   inline constexpr bool is_base_of_v = __is_base_of(_Base, _Derived);
      |                                                            ^
<source>:13:29: note: in instantiation of variable template specialization 'std::is_base_of_v<SomeSafeClassA, const (lambda at <source>:38:14)>' requested here
   13 | concept IsSafeClassA = std::is_base_of_v<SomeSafeClassA, T>;

现在 lambda - 如果它是一个完整的类型 - 无论如何都会失败
is_base_of
测试。我想要的是 lambda 匹配第一个模板特化;这个:

template<typename... Args>
struct coroutine_traits<TaskType<int>, Args...>{
    using promise_type = TaskType<int>;
};

不会因基于类的专业化的类型不完整而引发编译器错误。这些专门化适用于成员函数,与 lambda 完全无关,并且不应该被评估(或者至少被评估并且无法匹配,而不是导致编译错误)。
如何定义基于类的 

coroutine_traits

专业化而不导致 lambda 导致编译器错误?

	

我现在所做的是添加 lambda 可以返回的任务类型的更具体的专业化,例如
c++ lambda c++20 c++-concepts c++-coroutine
1个回答
1
投票
template <typename ResultType> class TLambdaTask : public TTask<ResultType> { public: // ... pass through any constructors down to TTask };

然后我可以为这个特定于 lambda 的类型定义一个专门化:
template <typename ReturnType, typename... Args>
struct coroutine_traits<TLambdaTask<ReturnType>, Args...>
{
    // using promise_type = ...
};

任何使用
co_await
的 lambda 都可以返回此特定于 lambda 的类型,该类型只能与

TLambdaTask

 特化匹配(而不是一般 
TTask
 的类特化):
auto k = []() -> TLambdaTask<int> {
    co_return 6;
};

不过,如果有人有办法在没有派生
TLambdaTask
类型的情况下完成这项工作,那就更理想了。

	

© www.soinside.com 2019 - 2024. All rights reserved.