![]()
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.