kev*_*man 4 recursion type-inference c++11 return-type-deduction c++14
使用一些Hindley-Milner类型推断变体的编程语言可以很容易地推断出表达式的类型,例如
let rec fix f x = f (fix f) x
Run Code Online (Sandbox Code Playgroud)
而C++ 1y中的返回类型推断因以下原因而失败:
int main() {
auto fix =
[&](auto f) {
return [&](auto x) {
return f(fix(f))(x);
};
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用clang 3.5和命令试了这个
clang++ -std=c++1y fix.cc
Run Code Online (Sandbox Code Playgroud)
我明白了
fix.cc:7:18: error: variable 'fix' declared with 'auto' type cannot appear in its
own initializer
return f(fix(f))(x);
Run Code Online (Sandbox Code Playgroud)
C++的返回类型推断中缺少什么,当必须推断返回类型时,它不允许在它自己的初始化器中使用变量?我可以做些什么来解决这个问题,更好的是,我们可以做些什么来解决这个问题?
这里的问题不是类型推断的问题.直接的问题很简单,即使这样做是完全合理和可实现的,lambda也不存在引用自身的语法.可以轻松定义引用自身的函数对象.
您的特定lambda有一个问题,即您通过引用捕获本地对象,然后允许该引用转义它有效的范围,但是如果我们将其更改为:
int main() {
auto fix =
[](auto &f) {
return [&](auto x) {
return f(fix(f))(x);
};
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以编写和使用等效的函数对象:
#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';
}
Run Code Online (Sandbox Code Playgroud)
如果添加了某种语法以允许lambda引用自身,那么这样就可以了.