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,提问作者康桓瑋
相关产品推荐
相关产品推荐

