c++ - 在实例化之前推断函数模板的返回类型
问题描述
这是递归函数的返回类型推导的后续问题。
template <class F>
struct y_combinator {
F f; // the lambda will be stored here
// a forwarding operator():
template <class... Args>
decltype(auto) operator()(Args&&... args) const {
// we pass ourselves to f, then the arguments.
// [edit: Barry] pass in std::ref(*this) instead of *this
return f(std::ref(*this), std::forward<Args>(args)...);
}
};
// deduction guide
template <class F> y_combinator(F) -> y_combinator<F>;
基本上,y_combinator
允许人们更轻松地编写递归 lambda 表达式(例如,无需删除 a std::function
)。
在这个问题中,考虑[dcl.spec.auto]/10不适用的情况(即递归调用之前没有返回语句)。
// this does not compile
y_combinator{
// lets call the lambda expression #1
[](auto g, int i) {
for (int j = i; j < 10; ++j) {
g(j + 1);
}
}}(1);
根据ecatmur对原始问题的回答,上面的代码失败了,因为
y_combinator<lambda #1>::operator()<int> instantiates
-> [lambda #1]::operator()<y_combinator<lambda #1>> instantiates
-> need to know return type of y_combinator<lambda #1>::operator()<int> at the point of g(j+1);
-> fail!
但是,编译器很可能知道 的返回类型在第一次实例化F::operator()
之前。void
y_combinator<lambda #1>::operator()<int>
为什么在构造
F::operator()
临时对象时不推导出lambda #1 的返回类型(以及因此的返回类型)?y_combinator
-> void
是否可以在不向lambda #1添加尾随返回类型的情况下编译代码?
解决方案
为了推断返回类型,编译器必须实例化泛型 lambda。它做到了,代码格式不正确,因为他无法推断出g(j+1)
.
为了能够编译此代码,编译器应该进行归纳:
- 让我们假设 的返回值
g(j+1)
使得通用 lambda 调用运算符实例化格式良好。 - 所以泛型 lambda 实例化成功,其返回类型为 void
- 所以 y_combinator 调用运算符返回类型为 void
- 所以确实第一个假设是正确的!
也许当编译器能够做到这一点时,计算机将自己编码!
所以不,不可能不使用尾随返回类型。或者做得更好,就用一个函数。Lambda 是导致模板实例化爆炸的恶魔。
推荐阅读
- python - 如何使用python杀死外部进程?
- mysql - mysql docker image 如何使用自己的用户名和密码创建数据库
- react-native - react native 中的上下滑动动画
- python - 当没有声明特定的重量衰减时,使用的标准重量衰减是什么?
- c - 为什么使用结构指针而不是结构变量创建链接列表?
- react-native - 在 React Native 中为度量选择创建自定义选择器的最佳方法是什么?
- laravel - 数据未显示在我的控制台中。在 vue 中登录
- python - 如何计算数据框中同一列中特定值之后的行数
- mysql - MySQL根据其他列值以增量方式更新列
- rx-java - rxJava如何在能够访问先前参数的同时进行顺序调用