C++26 補齊 callable wrapper 家族:copyable_function 修正 std::function 的 const-correctness 缺陷
C++26 標準 (P2548R6, P0792R14) · 2026-05-20
C++26 將在標準庫新增 std::copyable_function(提案 P2548R6)與 std::function_ref(提案 P0792R14),填補 std::function 與 C++23 的 std::move_only_function 之間的設計空白。前者修正 const-correctness 缺陷並保留可複製語意,後者提供零開銷的非擁有式引用。
copyable_function:修正 std::function 的歷史錯誤
std::function 有一個由來已久的設計缺陷:它的 operator() 宣告為 const,卻可以呼叫儲存物件的非 const operator()。這個不一致無法在不破壞 ABI 的情況下修正,因此 C++26 引入全新的 copyable_function,從零開始正確實作 const-correctness。
具體行為由模板簽名中的限定詞控制:
std::copyable_function<int()> f; // operator() 為非 const
std::copyable_function<int() const> g; // operator() 為 constcopyable_function 支援 cv/ref qualifiers 與 noexcept,要求儲存的 callable 必須是可複製建構的。它可以隱式轉換為 move_only_function,反向則不行。移除了 target() 與 target_type() 成員函式以降低實作複雜度。
function_ref:零開銷非擁有引用
std::function_ref 定位類似 std::string_view——不持有所有權、可平凡複製(trivially copyable)、無記憶體配置。沒有預設建構子和 operator bool,並禁止從非函式型別賦值以防懸掛引用。僅支援 const 與 noexcept 限定詞,不支援 ref-qualifiers。提案 P3961R1 修正 double indirection 問題並允許 noexcept 降級。
選用指南
function_ref:作為函式參數傳遞 callback,要求最低開銷move_only_function(C++23):儲存不可複製的 callable,如 task queue 的任務copyable_function:在新代碼中替代std::functionstd::function:不建議在新代碼中使用
Rust 多層存在類型的消除:vtable 設計限制與手動繞解方案
wolfgirl.dev · 2026-05-20
Rust 的 dyn Trait 提供單層存在量化(existential quantification)的自動消除:編譯器生成 vtable,讓呼叫方無需知道具體型別。但當需要同時對多個型別參數進行存在量化時,例如 ∃S, B. S: Generic<B>,Rust 的型別系統目前不提供自動支援。
核心問題
直覺上希望寫成類似 Box<dyn Generic<?>> 的形式,但 vtable 無法儲存關聯型別的不同實例化版本——不同的 B 意味著不同的函式簽名,也就是不同的 vtable 佈局,這在靜態分派的 vtable 模型下是根本矛盾。試圖用關聯型別折疊多個存在量化會觸發 Rust 的一致性規則(coherence rules):impl<B, S: Generic<B>> SingleAssociated for S 違規,因為對同一個 S 可能存在多個 B 的實作。
使用 PhantomData<B> 包裝成 (S, PhantomData<B>) 可繞過一致性問題,但一旦要存入 vtable,佈局差異的問題依然存在。
可行的手動消除方案
文章提出兩種實用路徑。第一種是定義包裝 trait,手動轉發所需操作:
trait Erased {
fn name(&self) -> &'static str;
}這對不需要在方法簽名中使用 B 的情況有效。當方法簽名需要 B 的參數或回傳值時,第二種方案是透過 std::any::Any 進行型別消除:將涉及 B 的參數與回傳值包裝為 Box<dyn Any>,在呼叫端以 .downcast_ref() 恢復具體型別。
影響範圍
單層 dyn Trait 的自動消除不受影響,這是 Rust 日常使用的基礎。多層存在量化的需求主要出現在需要在資料結構中儲存多型 callable 或複雜 trait 階層的場景,例如插件系統、事件匯流排、泛型資料管線。目前的繞解方案需要大量樣板代碼,作者提到巨集自動生成理論可行,但尚無已知 crate 實作。