捕获_this_的lambda中的函数名称解析

Ale*_*ban 3 c++ lambda visual-studio-2010 c++11 visual-studio-2012

我正在看下面的代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

(http://ideone.com/w7nyb)

VS2010呼叫,::f()但GCC和VS2012呼叫S::f().对我来说,似乎VS2012是正确的.

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

Jam*_*lis 5

S::f()应该叫.C++11§5.1.2/ 7指出:

所述λ-表达化合物语句产生的功能体的函数调用操作的,但对于名称查找的目的,确定的类型和值this和转化ID表达式参照非静态类成员变成类成员访问表达式使用时(*this),在lambda表达式的上下文中考虑复合语句.

这里的重要部分是"出于名称查找的目的,...... 复合语句lambda表达式的上下文中被考虑." 因为f在lambda块中没有声明本地声明,所以如果直接从body体中引用它,它就会被查找起来oops.因此,找到了成员函数.


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