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

时间:2012-10-15 23:41:02

标签: c++ visual-studio-2010 lambda 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;
}

http://ideone.com/w7nyb

VS2010呼叫::f()但是GCC&amp; VS2012呼叫S::f()。对我来说,似乎VS2012是正确的。

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

1 个答案:

答案 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最终确定之前,规范是一个移动目标,较旧的编译器可能会实现规范的不同修订。即使是现在,许多实施者仍在努力追赶最终的规范。