使用Hindley-Milner类推理的一些变体编程语言可以很容易地推断出表达式的类型,例如
let rec fix f x = f (fix f) x
而C ++ 1y中的返回类型推断因以下原因而失败:
int main() {
auto fix =
[&](auto f) {
return [&](auto x) {
return f(fix(f))(x);
};
};
return 0;
}
我用clang 3.5和命令
尝试了这个clang++ -std=c++1y fix.cc
我得到了
fix.cc:7:18: error: variable 'fix' declared with 'auto' type cannot appear in its
own initializer
return f(fix(f))(x);
在必须推断返回类型时,C ++的返回类型推断中缺少哪些不允许在其自己的初始化程序中使用变量?我可以做些什么来解决这个问题,更好的是,我们可以做些什么来解决这个问题呢?
答案 0 :(得分:5)
这里的问题不是类型推断的问题。直接的问题很简单,即使这样做是完全合理和可实现的,lambda也不存在引用自身的语法。可以很容易地定义函数对象来引用它们自己。
您的特定lambda有一个问题,即您通过引用捕获本地对象,然后允许该引用转义它有效的范围,但是如果我们将其更改为:
int main() {
auto fix =
[](auto &f) {
return [&](auto x) {
return f(fix(f))(x);
};
};
return 0;
}
然后我们可以编写和使用等效的函数对象:
#include <iostream>
struct lambda1 {
template<typename F>
auto operator() (F &f) const;
};
template<typename F>
struct lambda2 {
lambda1 const &l1;
F &f;
lambda2(lambda1 const &l1, F &f) : l1(l1), f(f) {}
template<typename X>
auto operator() (X x) const { return f( l1(f))(x); }
};
template<typename F>
auto lambda1::operator() (F &f) const {
return lambda2<F>(*this, f);
} // ^
// |
// --- there's no syntax to do this inside a lambda.
int main() {
lambda1 fix;
auto f = [](auto&&){ return [](int x) {return x;}; };
std::cout << fix(f)(5) << '\n';
}
如果添加某种语法以允许lambda引用自身,那么这样就可以了。