C++11 C++;1y返回类型推断

C++11 C++;1y返回类型推断,c++11,recursion,type-inference,c++14,return-type-deduction,C++11,Recursion,Type Inference,C++14,Return Type Deduction,具有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; } 我用叮当3.5和命令试过了 clang++

具有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;
}
我用叮当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++的返回类型推断不允许在它自己的初始值设定项中使用变量,它缺少什么?我能做些什么来解决这个问题,更好的是,我们能做些什么来解决语言中的这个问题?

这里的问题不是类型推断的问题。当前的问题只是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';
}
#包括
结构lambda1{
模板
自动运算符()(F&F)常量;
};
模板
结构lambda2{
lambda1常数&l1;
F&F;
lambda2(lambda1常数&l1,F&F):l1(l1),F(F){}
模板
自动运算符()(X)常量{返回f(l1(f))(X);}
}; 
模板
自动lambda1::运算符()(F&F)常量{
返回λ2(*此,f);
}   //                  ^
//                  |
//---没有语法在lambda中执行此操作。
int main(){
lambda1固定;
自动f=[](自动&&){return[](int x){return x;};};

std::cout我仍在努力理解它的作用(意图):如果你调用
fix
提供一个名为
fun
,那么
fix(fun)
会产生一些
[&](auto x){return fun(fix(fun))(x);}
,我可以递归地替换
fix(fun)
使用上述表达式。即使
fun
有一个不依赖于参数的固定返回类型,我也看不出这个递归是如何结束的。显然,你可以访问isocpp.org,找到关于编写建议的说明,编写一个建议标准的新措辞,详细解释为什么这个扩展不会引起麻烦,等等@ Dyp,你不递归替换FIX(FILY)。FIX(FAY)返回函数对象G(x)调用f(g)以获得函数(对象)h,然后调用H(x)。有些人喜欢调用C++之类的语言执行“类型推导”而不是“类型推断”(有时是“完全类型推断”)。。前者没有后者所暗示的权重和形式化。不过,这可能只是我对事物的看法。我对C++1y lambdas有所了解。尝试省略尽可能多的显式返回类型以查看编译器如何处理它非常有趣。在任何情况下,我都无法确定何时以及为什么需要任何返回类型。with是一个(无用的)调用。上面的问题是,除非调用
操作符()
主体,否则它不会被编译。@Yakk在我的程序中,模板操作符()没有实例化,但它可以被实例化,并且它在没有任何修改的情况下正常工作:nod——你会注意到(除了一些完美的转发之外)我的代码与你的代码完全相同。我只是注意到上面代码中缺失的部分,我觉得我必须检查以确保它实际工作。:@Yakk啊,好的。我已经修改了我的答案,以实际实例化并运行代码。