stdexec中__completion_signature概念、代码解析及completion_signatures用途咨询
关于NVIDIA stdexec中__completion_signature与相关组件的解析
1. __completion_signature概念的作用
__completion_signature是stdexec内部用来验证类型是否符合P2300提案定义的「完成签名」格式的概念。
完成签名是Sender描述自身完成行为的核心类型,必须是以下三种形式之一:
set_value_t(Args...):表示Sender正常完成时,会传递Args...类型参数给Receiver的set_value方法set_error_t(Error):表示Sender出错时,会传递Error类型的错误信息给Receiver的set_error方法set_stopped_t():表示Sender被取消时,会调用Receiver的set_stopped方法
这个概念通过重载解析+SFINAE机制实现:
- 若传入类型是合法的非
noexcept完成签名,会匹配前三个__test重载,返回合法的__types实例,使__typename<decltype(...)>条件成立,概念满足 - 若传入的是
noexcept修饰的完成签名,会匹配被delete的重载,触发编译错误,概念不满足 - 若传入非法格式的类型,会匹配
__test(...)重载,返回__types<>,同样不满足__typename要求,以此过滤非法签名
2. __types<__minvoke<...>>的具体含义
这些是stdexec内部的元编程工具组合,用于辅助完成签名的验证逻辑:
__types:stdexec内置的类型列表容器,用于打包一组类型__q<__types>:将__types包装为元函数对象,用于元编程中的类型操作__minvoke:元调用工具,负责调用元函数对象并传递类型参数
以第一个重载为例:
__types<__minvoke<_Ty, _Args...>> __test(_Tag (*)(_Args...));
当_Ty使用默认值__q<__types>时,__minvoke<__q<__types>, _Args...>等价于__types<_Args...>,因此整个返回类型是__types<__types<_Args...>>。
这个结构的核心目的不是返回具体类型,而是确保传入合法完成签名时,__test调用能返回一个可被__typename识别的合法类型,从而让__completion_signature概念成立。
3. Sender示例
以下是一个简单的立即返回整数值的Sender实现,符合stdexec的sender概念要求:
#include <stdexec/execution.hpp> #include <iostream> // 立即返回42的Sender struct immediate_int_sender { // 暴露完成签名:仅会以int类型正常完成 friend auto tag_invoke(stdexec::get_completion_signatures_t, immediate_int_sender) -> stdexec::completion_signatures<stdexec::set_value_t(int)>; // 定义操作状态:负责执行Sender的核心逻辑 template <stdexec::receiver Receiver> struct op_state { Receiver rcvr_; void start() noexcept { // 完成时调用Receiver的set_value,传递42 stdexec::set_value(std::move(rcvr_), 42); } }; // 实现connect:绑定Receiver与Sender,返回操作状态 template <stdexec::receiver Receiver> friend auto tag_invoke(stdexec::connect_t, immediate_int_sender, Receiver rcvr) -> op_state<Receiver> { return {std::move(rcvr)}; } }; // 静态验证该类型符合sender概念 static_assert(stdexec::sender<immediate_int_sender>); int main() { // 创建Sender实例 auto sndr = immediate_int_sender{}; // 创建Receiver:处理三种完成情况 auto rcvr = stdexec::receiver{ [](int val) { std::cout << "收到值:" << val << std::endl; }, [](std::exception_ptr) { std::cout << "发生错误" << std::endl; }, []() { std::cout << "操作被取消" << std::endl; } }; // 绑定Sender与Receiver,获取操作状态 auto op = stdexec::connect(std::move(sndr), std::move(rcvr)); // 启动操作 stdexec::start(op); return 0; }
4. completion_signatures的用途
completion_signatures是一个类型集合容器,专门用于封装Sender的所有完成签名,核心用途包括:
- 静态暴露完成行为:Sender通过
get_completion_signatures标签函数返回completion_signatures实例,让编译器和其他组件明确该Sender可能的完成路径(正常返回、出错、被取消) - 编译期兼容性检查:Receiver可以基于这个集合,在编译期验证自己是否能处理Sender的所有完成情况(比如是否有对应的
set_value/set_error/set_stopped重载) - 元编程基础:stdexec的调度器、适配器等组件可以基于这个集合进行元编程,实现自动适配、类型推导等功能
内容的提问来源于stack exchange,提问作者Frederic Schönberger
相关产品推荐
相关产品推荐

