据我所知,所有数据类型必须在编译时知道,而lambda不是类型。 lambda是否被翻译成anonymous struct with operator()
或std::function
包裹?
例如,
std::for_each(v.begin(), v.end(), [](int n&){n++;});
答案 0 :(得分:14)
as-if rule的变体,C ++ 11标准说:
§5.1.2/ 3 [..] 实现可以定义闭包类型 与下面描述的不同,只要不改变 程序的可观察行为,而不是改变:
- 闭包类型的大小和/或对齐方式
- 闭包类型是否可以轻易复制(第9条),
- 闭包类型是标准布局类(第9条)还是
- 闭包类型是否为POD类(第9条)。
我相信这就是人们说unspecified时的意思。但是,其他答案中已经说明的保证如下:
[C++11: 5.1.2/3]:
lambda-expression 的类型(也是闭包对象的类型)是一个唯一的,未命名的 非联合类类型 - 称为闭包类型 - 其属性 如下所述。此类类型不是聚合(8.5.1)。该 闭包类型在最小的块范围,类范围或 包含相应 lambda-expression 的命名空间范围。 [..]该子句继续列出此类型的不同属性。这是 一些亮点:
[C++11: 5.1.2/5]:
lambda-expression 的闭包类型有一个公共inline
函数调用运算符(13.5.4),其参数和 返回类型由 lambda-expression 描述 分别是 parameter-declaration-clause 和 trailing-return-type 。 [..]
[C++11: 5.1.2/6]:
没有 lambda-capture 的 lambda-expression 的闭包类型具有公共非虚拟非显式const 转换函数指向具有相同参数的函数 并返回类型作为闭包类型的函数调用操作符。该 此转换函数返回的值应为a的地址 调用时的函数与调用函数具有相同的效果 闭包类型的函数调用操作符。
答案 1 :(得分:12)
从标准§5.1.2.3:
lambda-expression 的类型是一个唯一的,未命名的非联合类类型
这是它自己的类型。每次。例如:
auto a = []{ return 1; };
auto b = []{ return 1; };
a
和b
必然会有不同的类型。它们都可以转换为std::function<int()>
,但不能转换为彼此:
std::function<int()> c = a; // OK
a = b; // NOPE
添加一些示例以增加一些清晰度:
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()>
答案 2 :(得分:6)
lambda表达式构造一个未命名的类型,每个类型具有不同的类型。它们不是std::function
实现。更多信息请点击此处:
What is a lambda expression in C++11?和此处:How to convert a lambda to an std::function using templates
您可以使用以下技巧在特定编译器上公开类型:
void foo(int);
int main() {
auto a = []{ return 1; };
auto b = []{ return 1; };
foo(a);
foo(b);
return 0;
}
在我的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);
@Barry指出您可以使用typeid
代替。如果我在我的系统上打印出typeid(a).name()
和typeid(b).name()
,我会得到:
Z4mainE3$_0
Z4mainE3$_1
哪个demangle到
main::$_0
main::$_1
只是想把它包括在内以保持完整性。我实际上发现错误消息版本更具信息性。 :)