3

我正在查看以下代码:

#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;
}

( http://ideone.com/w7nyb )

VS2010 调用::f()但 GCC & VS2012 调用S::f()。对我来说,VS2012 似乎是正确的。

根据标准应该调用哪个函数?

4

1 回答 1

5

S::f()应该调用。C++11 §5.1.2/7 状态:

lambda-expression复合语句产生函数调用运算符的函数,但出于名称查找的目的,确定引用非静态类成员的id 表达式this的类型和值并将其转换为类成员访问表达式使用,在lambda-expression的上下文中考虑复合语句(*this)

这里的重要部分是“出于名称查找的目的,......复合语句在lambda-expression的上下文中被考虑。” 由于在 lambda 块中没有f本地声明,因此查找它就像直接从oops. 因此,找到了成员函数。


请注意,最新版本的 Visual C++ 和 gcc 都具有正确的行为(包括 Visual C++ 2012 和 gcc 4.7.2)。旧版本可能会表现出不正确的行为,因为 lambda 规范在 2009 年下半年进行了大修(请参阅n2927:C++0x Lambdas 的新措辞[PDF])。请记住,在 C++11 最终确定之前,规范是一个移动的目标,旧的编译器可能会实现规范的不同版本。即使是现在,许多实施者仍在努力赶上最终规范。

于 2012-10-15T23:49:45.100 回答