lambda被编译成什么类型​​?

tex*_*uce 18 c++ lambda c++11

据我所知,所有数据类型必须在编译时知道,而lambda不是一个类型.lambda被翻译成anonymous struct with operator()std::function包裹?

例如,

std::for_each(v.begin(), v.end(), [](int n&){n++;});
Run Code Online (Sandbox Code Playgroud)

小智 14

C++ 11标准的as-if规则的变体说:

§5.1.2/ 3 [..]实现可以定义闭包类型与下面描述的不同,前提是这不会改变程序的可观察行为,只需更改:

- 封闭类型的大小和/或对齐方式,

- 封闭类型是否可以轻易复制(第9条),

- 闭包类型是否为标准布局类(第9条),或

- 闭包类型是否为POD类(第9条).

我相信这就是人们说它没有具体说的意思.但是,其他答案中已经说明的保证如下:

原作者:轨道中的轻盈竞赛

[C++11: 5.1.2/3]: 的类型的λ-表达(这也是封闭的对象的类型)是一个独特的,无名不愈合类类型 -称为闭合类型 -其特性如下所述.此类类型不是聚合(8.5.1).闭包类型在包含相应lambda表达式的最小块作用域,类作用域或命名空间作用域中声明. [..]

该子句继续列出此类型的不同属性.以下是一些亮点:

[C++11: 5.1.2/5]:lambda表达式的闭包类型有一个公共inline函数调用操作符(13.5.4),其参数和返回类型分别由lambda-expressionparameter-declaration-clausetrailing-return-type描述.[..]

[C++11: 5.1.2/6]:没有lambda-capturelambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数.此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果.


Bar*_*rry 12

从标准§5.1.2.3开始:

lambda-expression的类型是一个唯一的,未命名的非联合类类型

这是它自己的类型.每次.例如:

auto a = []{ return 1; };
auto b = []{ return 1; };
Run Code Online (Sandbox Code Playgroud)

a并且b必然会有不同的类型.它们既可以转换std::function<int()>为彼此,也可以不转换为彼此:

std::function<int()> c = a; // OK
a = b; // NOPE
Run Code Online (Sandbox Code Playgroud)

添加一些示例以增加一些清晰度:

decltype(a) a2 = a; // OK, explicitly specifying the correct type

template <typename F>
void foo(F f) { ... }

foo(a); // calls foo<decltype(a)>, not foo<std::function<int()>
Run Code Online (Sandbox Code Playgroud)

  • @texasbruce你误解了.他们*做*有类型.它只是*唯一*和*未命名*.在我的例子中,你可以做`使用T = decltype(a); T a2 = a;`那将编译得很好. (5认同)

sfj*_*jac 6

lambda表达式构造一个未命名的类型,每个类型具有不同的类型.它们不是std::function实现.这里提供了更多信息: C++ 11中的lambda表达式是什么?这里:如何使用模板将lambda转换为std :: function

您可以使用如下方法在特定编译器上公开类型:

void foo(int);

int main() {
    auto a = []{ return 1; };
    auto b = []{ return 1; };

    foo(a);

    foo(b);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在我的mac上用clang编译给出:

/Users/jcrotinger/ClionProjects/so_lambda_type/main.cpp:11:5: error: no matching function for call to 'foo'
    foo(a);
    ^~~
/Users/jcrotinger/ClionProjects/so_lambda_type/main.cpp:5:6: note: candidate function not viable: no known conversion from 
'<lambda at /Users/jcrotinger/ClionProjects/so_lambda_type/main.cpp:8:14>' to 'int' for 1st argument
void foo(int);
     ^
/Users/jcrotinger/ClionProjects/so_lambda_type/main.cpp:13:5: error: no matching function for call to 'foo'
    foo(b);
    ^~~
/Users/jcrotinger/ClionProjects/so_lambda_type/main.cpp:5:6: note: candidate function not viable: no known conversion from 
'<lambda at /Users/jcrotinger/ClionProjects/so_lambda_type/main.cpp:9:14>' to 'int' for 1st argument
void foo(int);
Run Code Online (Sandbox Code Playgroud)

@Barry指出你可以typeid改用.如果我打印出来typeid(a).name()typeid(b).name()我的系统上,我得到:

Z4mainE3$_0
Z4mainE3$_1
Run Code Online (Sandbox Code Playgroud)

哪个消解了

main::$_0
main::$_1
Run Code Online (Sandbox Code Playgroud)

只是想把它包括在内以保证完整性.我实际上发现错误消息版本更具信息性.:)


归档时间:

查看次数:

1936 次

最近记录:

10 年,10 月 前