![]()
2300行提案,7轮修订,C++标准委员会终于松口。P2300——这个让圈内人又爱又恨的异步编程模型——正式锁定C++26。但反对声浪从没停过:「有协程了还要这玩意?」「太复杂,看不懂。」
提案核心作者之一、微软资深工程师Eric Niebler最近写了篇长文回应。他没讲大道理,而是搬出一套Win32老代码——那种你我都写过的、带回调的异步IO。他的论点很直接:senders不是来替代协程的,是来收拾烂摊子的。
回调的问题从来不是「能用」,而是「每家都不一样」
Win32的ReadFileEx长这样:传一个overlapped结构体指针,再传一个回调函数指针。IO完成时,系统把结构体塞回给你。写过的人熟悉这套——new一个派生结构体,塞点自定义数据,回调里static_cast转回来,最后delete收尾。
Niebler说他写过几百次。你我大概也差不多。
这套机制本身没毛病。真正的麻烦在于:每个库的回调形状都不一样。有的用void(*)(int, void*),有的用std::function,有的要求你继承特定基类,有的玩状态机。想把两个不同库的异步操作串起来?先写100行胶水代码,处理类型转换、生命周期、错误传播。
「胶水代码」是个被低估的灾难。它不创造业务价值,却吞噬调试时间。更隐蔽的是,每个开发者都在重复造轮子——A项目写的适配器,B项目用不了,因为底层库版本差了一代。
Senders的本质:把「怎么做」和「什么时候做」拆开
P2300的核心设计很朴素。一个sender(发送器)描述「要做什么」,但不立刻执行。执行时机交给scheduler(调度器)决定。这有点像你把外卖订单提交给平台,具体哪家骑手接单、走哪条路,你不管了。
代码层面,sender是个轻量级对象,可以复制、可以组合。用管道操作符|把多个sender串成链,错误处理、取消信号、执行上下文都在链上显式声明。Niebler展示的改造案例里,那段Win32回调被包进一个sender后,调用方写成这样:
auto snd = read_file_sender(file, buffer) | then(process) | on(thread_pool);
没有裸指针,没有手动内存管理,没有「这个回调在哪个线程跑」的猜测。线程池、GPU、IOCP——切换scheduler就行,业务逻辑不动。
协程能做到这些吗?能,但代价不同。C++20协程是「从内到外」的:你写一个协程函数,编译器帮你拆成状态机,调用方用co_await驱动。这很好,直到你需要把协程和遗留回调代码接在一起——又是一场类型体操。
Senders是「从外到内」的:先把异步来源统一成sender,再用算法组合。Niebler的比喻是,协程像一门编程语言,senders像标准库——两者协作,而非互斥。
「复杂」的指控,有多少是文档的锅?
Niebler在文章里认了错:「我们 collectively 做了 terrible job,让这工作变得accessible。」P2300的正式文本确实吓人——概念(concept)、约束、模板元编程满天飞。但作者团队正在推一个简化版核心,把森林和树分开。
他展示的改造案例只有几十行。真正的学习曲线不在语法,而在思维转换:停止思考「回调什么时候被调用」,开始思考「这个操作的依赖图长什么样」。
一个细节值得玩味。Niebler提到,sender的设计深受函数式编程影响——特别是Haskell的IO monad。但C++社区对「monad」这个词过敏,所以文档里避而不谈,结果反而让概念更难解释。有时候,诚实面对借鉴来源,比假装原创更清晰。
标准之争背后:谁为「生态碎片」买单
P2300进C++26不代表尘埃落定。GCC、Clang、MSVC的实现进度不一,第三方库(如Boost.Asio、libunifex)的迁移策略也在博弈。但标准存在的意义,是给「异步编程该长什么样」一个参考答案。
没有标准时,每个大厂推自己的方案:微软有PPL,Facebook有Folly,Google有libasync。小公司夹在中间,选边站队或重复造轮。P2300至少提供了一个最大公约数——不完美,但可协商。
Niebler的文章结尾没喊口号。他放了一段改造后的完整代码,然后说:「这就是全部了。没有魔法。」
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.