我正在查看以下代码:
#include <iostream>
void f()
{
std::cout << "Called ::f()" << std::endl;
}
struct S
{
void f()
{
std::cout << "Called S::f()" << std::endl;
}
void oops()
{
[this](){ f(); }(); // calls the wrong function
}
};
int main()
{
S().oops();
return 0;
}
VS2010呼叫::f()
但是GCC&amp; VS2012呼叫S::f()
。对我来说,似乎VS2012是正确的。
应该根据标准调用哪个函数?
答案 0 :(得分:5)
S::f()
。 C ++11§5.1.2/ 7声明:
lambda-expression 的复合语句产生函数调用运算符的 function-body ,但出于名称查找的目的,使用
的上下文中被考虑this
确定(*this)
的类型和值,并将引用非静态类成员的 id-expressions 转换为类成员访问表达式, compound-statement 在 lambda-expression 。
这里的重要部分是“出于名称查找的目的,...... 复合语句在 lambda-expression 的上下文中被考虑。”由于在lambda块中没有本地声明f
,因此如果直接从oops
的主体引用它,就会查找它。因此,找到了成员函数。
请注意,最新版本的Visual C ++和gcc都具有正确的行为(包括Visual C ++ 2012和gcc 4.7.2)。较旧的版本可能表现出不正确的行为,因为lambda规范在2009年下半年进行了彻底检查(参见n2927: New wording for C++0x Lambdas [PDF])。请记住,在C ++ 11最终确定之前,规范是一个移动目标,较旧的编译器可能会实现规范的不同修订。即使是现在,许多实施者仍在努力追赶最终的规范。