为什么成员函数-try-block处理程序中的lambda(捕获'this')不能访问VC++ 2013中的私有数据成员?

Mec*_*eer 5 c++ lambda visual-c++ c++11 visual-studio-2013

关于静态初始化器的这个问题可能与此不一致但可能相关.

这里前两个函数编译正常,最后一个函数不是在vc ++中,而是在clang和gcc中:

class A {
protected:
    std::string protected_member = "yay";
public:
    void withNormalBlock();
    void withFunctionBlock();
    void noLambda();
};


void A::withNormalBlock() {
    try {
        throw std::exception();
    } catch (...) {
        [this]() {
            std::cout << protected_member << std::endl;
        }();
    }
}

void A::noLambda() try {
    throw std::exception();
} catch (...) {
    std::cout << protected_member << std::endl;
}

void A::withFunctionBlock() try {
    throw std::exception();
} catch (...) {
    [this]() {
        // this line is the problem:
        std::cout << protected_member << std::endl;
    }();
}
Run Code Online (Sandbox Code Playgroud)
  • 在铿锵(好的)
  • 在gcc(好的)
  • 在vc ++(error C2248: 'A::protected_member' : cannot access protected member declared in class 'A')中
  • vc ++ 2015 - 同样的交易

我在标准中找不到任何建议函数try-block的handler/catch块应该免于函数范围或者lambda的闭包类型应该改变.如果访问类型更改为所有公共,则代码将进行编译.

根本原因是什么?它是一个错误,还是可以更改的编译器设置特有的?

Rud*_*lis 2

似乎这是一个错误,并且作用域中的 lambdacatch是在类作用域之外生成的。我试图用 typeids 来证明这一点,但是 Visual Studio lambda 名称被奇怪地破坏了,并且名称本身并不能证明任何事情。但是,以下代码片段生成的错误代码显示名称不同:

#include <iostream>
#include <typeinfo>

class Foo {
private:
public:
    void testLambda()
    try {
        auto tryScope = [this]() {};
        void (*p)() = tryScope;
    }
    catch(...)
    {
        auto catchScope = [this]() {};
        void (*p)() = catchScope;
    }

};
Run Code Online (Sandbox Code Playgroud)

错误输出:

(10): error C2440: 'initializing' : cannot convert from 'Foo::testLambda::<lambda_8a3a8afea7359de4568df0e75ead2a56>' to 'void (__cdecl *)(void)' (15): error C2440: 'initializing' : cannot convert from '<lambda_8cbc08e7748553fb5ae4e39184491e92>' to 'void (__cdecl *)(void)'