Dan*_*rey 255 c++ lambda operator-overloading language-lawyer c++11
在Stack Overflow问题中,在C++ 11中不允许重新定义lambda,为什么?,给出了一个不编译的小程序:
int main() {
auto test = []{};
test = []{};
}
Run Code Online (Sandbox Code Playgroud)
问题得到了回答,一切似乎都很好.然后是Johannes Schaub并做了一个有趣的观察:
如果你
+
在第一个lambda之前放置一个,它会神奇地开始工作.
所以我很好奇:为什么以下工作呢?
int main() {
auto test = +[]{}; // Note the unary operator + before the lambda
test = []{};
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*rey 240
是的,代码符合标准.所述+
触发转换为拉姆达一个普通的旧函数指针.
这是怎么回事:
编译器看到第一个lambda([]{}
)并根据§5.1.2生成一个闭包对象.由于lambda 是非捕获 lambda,以下适用:
5.1.2 Lambda表达式[expr.prim.lambda]
6没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数.此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果.
这很重要,因为一元运算符+
有一组内置的重载,特别是这一个:
13.6内置运算符[over.built]
8对于每种类型
T
,都存在表单的候选运算符函数
T* operator+(T*);
有了这个,很明显会发生什么:当operator +
被应用于闭包对象时,重载的内置候选集包含一个转换为任意指针,闭包类型只包含一个候选:转换为函数lambda的指针.
因此推断出test
in 的类型.现在第二行很简单:对于第二个lambda/closure对象,对函数指针的赋值触发与第一行相同的转换.即使第二个lambda具有不同的闭包类型,结果函数指针当然也是兼容的并且可以被赋值.auto test = +[]{};
void(*)()
归档时间: |
|
查看次数: |
25044 次 |
最近记录: |