在C ++ 0x中,我想知道lambda函数的类型是什么。具体做法是:
#include<iostream>
type1 foo(int x){
return [x](int y)->int{return x * y;};
}
int main(){
std::cout<<foo(3)(4);//would output 12
type2 bar = foo(5);
std::cout<<bar(6);//would output 30
return 0;
}
我需要更换type1 / type2以使上述功能正常工作?希望你能看到我想要完成的事情,所以即使直接替换type1和type2是不可能的,也许你可以引导我朝着正确的方向前进。
换句话说:
谢谢!
编辑:我正在使用visual studio 2010进行编译
答案 0 :(得分:14)
你永远不会知道lambda函数的类型,因为逻辑上发生的是编译器生成一个(本地)类,函数调用运算符重载,词法闭包由该(本地)类的数据成员表示。这是lambda函数逻辑上发生的事情,例如:
auto foo = [](int x, int y) { return x + y; };
编译器在逻辑上执行此操作:
struct CompilerGeneratedName { void operator()(int x, int y) const { return x + y; } };
CompilerGeneratedName foo;
由于编译器生成一个(本地)类,它会生成一个名称,因此您永远不能显式写入该类型,您只能从模板函数参数的类型推导或使用auto / decltype中推断出类型。
此外,C ++ 0x闭包是静态分配的,因此无论如何都无法安全地返回原始C ++ 0x闭包。
仍有几种方法可以实现这一点,第一种方法更灵活,并支持捕获词法范围的lambda函数。使用std :: function,如果你有一个lambda函数没有从外部作用域捕获任何东西,那么你可以使用函数指针,但这种转换更适合处理遗留代码而不是任何东西。
基本上你想要的是这个:
std::function< int (int) > foo(int x)
{
return [x](int y)->int{return x * y;};
}
我之所以继续逻辑地说,是因为这是boost :: lambda最初的工作原理(即使C ++ 03不允许在模板函数参数中使用本地类)以及添加的想法lambda函数起源于但是由于这是一种语言特性,现在编译器供应商可以以不同且更有效的方式实现它,例如当通过引用捕获所有环境时,编译器可以只传递指向调用堆栈的指针而不是逻辑方式保持逻辑视图。
答案 1 :(得分:6)
来自Wikipedia:
Lambda函数是依赖于实现的类型的函数对象;此类型的名称仅供编译器使用。如果用户希望将lambda函数作为参数,则类型必须是模板类型,或者必须创建
std::function
以捕获lambda值。
VC10编译此
//Beware, brain-compiled code ahead!
#include<iostream>
#include<functional>
std::function<int(int)> foo(int x)
{
return [x](int y)->int{return x * y;};
}
int main(){
std::cout<<foo(3)(4) << '\n';
auto bar = foo(5);
std::cout<<bar(6) << '\n';
return 0;
}
并打印
12 30