这个问题在这里已有答案:
在Stack Overflow问题Redefining lambdas not allowed in C++11, why?中,给出了一个不编译的小程序:
int main() {
auto test = []{};
test = []{};
}
问题得到了回答,一切似乎都很好 . 然后来了Johannes Schaub并制作了an interesting observation:
如果你在第一个lambda之前放置一个,它会神奇地开始工作 .
所以我很好奇:为什么以下工作呢?
int main() {
auto test = +[]{}; // Note the unary operator + before the lambda
test = []{};
}
1 回答
是的,代码符合标准 .
+
触发转换为lambda的普通旧函数指针 .这是怎么回事:
编译器看到第一个lambda(
[]{}
)并根据§5.1.2生成一个闭包对象 . 由于lambda是 non-capturing lambda,以下情况适用:这很重要,因为一元运算符
+
有一组内置的重载,特别是这一个:有了这个,很明显会发生什么:当operator
+
应用于闭包对象时,重载的内置候选集包含一个转换为任意指针,闭包类型只包含一个候选:转换为lambda的函数指针 .auto test = +[]{};
中test
的类型因此推断为void(*)()
. 现在第二行很简单:对于第二个lambda / closure对象,对函数指针的赋值触发与第一行相同的转换 . 即使第二个lambda具有不同的闭包类型,结果函数指针当然是兼容的并且可以被赋值 .