You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++23的std::move_only_function为何没有CTAD类模板推导指引?

为什么C++23不为std::move_only_function提供CTAD支持?

C++23 引入了与std::function同类的组件std::move_only_function,顾名思义,它是面向仅可移动可调用对象的仅可移动包装器,用法示例如下:

#include <functional>
#include <memory>

int main() {
  auto l = [p = std::make_unique<int>(0)] { };
  std::function<void(void)>           f1{std::move(l)}; // 编译不合法
  std::move_only_function<void(void)> f2{std::move(l)}; // 编译合法
}

但与std::function自带CTAD(类模板实参推导)指引不同,C++标准没有为std::move_only_function定义类模板推导指引,如下代码无法正常编译:

#include <functional>

int func(double) { return 0; }
int main() {
  std::function f1{func};           // 可正常推导为std::function<int(double)>
  std::move_only_function f2{func}; // 推导失败
}

标准没有添加对应CTAD支持的核心原因如下:

  • std::move_only_function支持的可调用签名形式远多于std::function,无法推导得到无歧义的唯一签名。
    std::function仅支持无额外限定的普通函数签名,CTAD逻辑简单,仅能处理普通函数、成员函数、无重载/无模板调用运算符的可调用对象。而std::move_only_function额外支持noexcept限定、const/volatile限定、调用值类别(左值/右值)限定的签名,比如void() const noexcept、int(double) &&都是合法的签名形式。同一个可调用对象通常可以匹配多种合法的std::move_only_function签名,没有统一的优先级规则能确定唯一的最优推导结果,强制添加CTAD会在大量场景下出现歧义,或是得到不符合用户预期的结果。
  • std::function的CTAD本身存在明显局限性,比如面对有重载operator()的可调用对象时就会直接推导失败,标准委员会不希望将这种有缺陷的设计延续到新的标准组件中,因此最终没有为std::move_only_function添加CTAD支持。

内容的提问来源于stack exchange,提问作者康桓瑋

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 16:15:03