静态成员初始值设定项的lambda范围

use*_*253 9 c++ lambda c++11

我的问题是关于静态成员初始值设定项的lambda范围.考虑以下测试:

#include <functional>
#include <iostream>

struct S {
    static const std::function<void(void)> s_func;
};

const std::function<void(void)> S::s_func = []() {
    std::cout << "Hello from " << __PRETTY_FUNCTION__ << std::endl;
};

int main(void) {
    S::s_func();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

从4.8开始的gcc定义了S范围内的lambda,所以程序输出如下:

Hello from S::<lambda()>
Run Code Online (Sandbox Code Playgroud)

(gcc-4.8.2对__FUNCTION__&Co宏有不同的定义,但是lambda仍在其中定义S)

同时gcc-4.7定义了全局范围内的lambda,因此程序输出

Hello from <lambda()>
Run Code Online (Sandbox Code Playgroud)

可能更新的gcc更符合标准.但是,我想询问标准是否实际指定了这个方面,或者它是否可以依赖于实现.

更新:因为@ user5434961建议所有__FUNCTION__相似的宏都依赖于实现,因此最好在符合标准的测试中避免使用它们.所以这里是一个例子,如果编译器在S范围内定义了这样的lambdas 并且打破了编译,则可以编译它:

#include <functional>
#include <iostream>

struct S {
    static const std::function<void(void)> s_func;
private:
    static const int s_field;
};

const std::function<void(void)> S::s_func = []() {
    std::cout << "Hello from S::s_func. S::s_field = " << S::s_field << std::endl;
};

const int S::s_field = 1;

int main(void) {
    S::s_func();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

use*_*961 7

此问题之前已经提出,但我找不到相关的错误报告.这是一个据称已提交的MSVC错误报告的断开链接(它在2015年仍未修复:您可以在rise4fun进行测试).然而,对于海湾合作委员会,它已被固定在4.7到4.8之间.用于支持这个错误的相关标准是:

[C++ 11,9.4.2/2] static数据成员定义中的初始化表达式 属于其类的范围.

[C++ 11,5.1.2/2] lambda表达式的评估导致prvalue临时(12.2).这个临时对象称为闭包对象.lambda表达式不应出现在未评估的操作数中(第5条).

[C++ 11,5.1.2/3] lambda表达式的类型(也是闭包对象的类型)是一个唯一的,未命名的非联合类类型 - 称为闭包类型 - 其属性被描述下面.此类类型不是聚合(8.5.1).闭包类型在包含相应lambda表达式的最小块作用域,类作用域或命名空间作用域中声明.

先前

为什么静态初始化程序中的lambda无法访问VC++ 2013中的类的私有成员?

C++ 11 lambda可以访问我的私有成员.为什么?

为什么不能在lambda中使用私有方法?