c++ - 为什么 C++23 std::move_only_function 没有推导指南?
问题描述
C++23 引入了std::function
的表亲std::move_only_function
,就像它的名字一样,它是一个只移动可调用对象(demo)的只移动包装器:
#include <functional>
#include <memory>
int main() {
auto l = [p = std::make_unique<int>(0)] { };
std::function<void(void)> f1{std::move(l)}; // ill-formed
std::move_only_function<void(void)> f2{std::move(l)}; // well-formed
}
但与 不同std::function
的是,该标准没有为其定义演绎指南(演示):
#include <functional>
int func(double) { return 0; }
int main() {
std::function f1{func}; // guide deduces function<int(double)>
std::move_only_function f2{func}; // deduction failed
}
有禁止 CTAD 的理由吗?
解决方案
类型擦除包装器之类move_only_function
的设计用于在 API 边界上使用,其中类型是显式的,这使得 CTAD 对这些有用的可疑之处。
无论如何,这些可调用包装器的任何 CTAD 都必须非常有限——它不能处理重载函数或函数模板,这也意味着它不能处理泛型 lambda,这是对其有用性的一个相当大的限制。std::function
的 CTAD 还附带了免责声明,以后的标准可以更改推导的类型(我们还没有更改,但我们也没有删除免责声明)。
并且move_only_function
不仅仅是推导出的返回和参数类型。const
, noexcept
, 和ref-qualifiers都在起作用,这引入了新的设计问题。例如,是否从 deduc 进行int (*)(int)
演绎int(int)
?为什么不int(int) const
——毕竟函数指针是可调用的?
如果 CTAD 被证明是必要的——并且有人为它想出了一个好的设计——它总是可以在以后添加。
我不知道这些观点是否都在 LEWG 讨论中提出(会议记录相当稀少),但我认为它们足以证明不支持 CTAD 是正当的。
推荐阅读
- firebase - 如何协调 StreamBuilder 的授权和 FutureBuilder 的数据来自 api 和 listview 过滤
- java - 在 Android WebView 上访问位置
- python - 日期所需的 strptime 日期格式,例如 `12/06/16 19:33`
- zurb-foundation - Foundation Zurb 当 Reveal 开场动画完成后,做某事
- reactjs - 意外的令牌,预期的“)”在 axios try-catch 语句中
- html - html中的导航问题
- mongodb - 在mongodb的字符串数组中查找和替换
- django - 如何在 django 中循环查询?
- javascript - 在生产构建中是否可以(全局)访问反应状态变量?
- mfc - C++(MFC) - 对话框阴影残像