静态成员初始化器的Lambda作用域
lambda scope for static members initializer
我的问题是关于静态成员初始化式的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;
}
gcc从4.8开始在S范围内定义了lambda,因此程序输出如下所示:
Hello from S::<lambda()>
(gcc-4.8.2)对__FUNCTION__
&但是,lambda仍然在S
同时gcc-4.7在全局作用域中定义了lambda,因此程序输出
Hello from <lambda()>
可能更新的gcc更符合标准。然而,我想问的是,标准是否确实规定了这方面,或者它可以依赖于实现。
Update: as @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;
}
这个问题之前已经提出,但我找不到相关的错误报告。这里是一个MSVC错误报告的链接,据说是提交的(它在2015年仍然没有修复:你可以在rise4fun上测试它)。然而,它已经在GCC的4.7和4.8之间修复了。用于将其作为bug进行备份的相关标准是:
以前[c++ 11, 9.4.2/2]的初始化表达式
static
数据成员在其类的作用域中。[c++ 11, 5.1.2/2] lambda表达式的求值导致一个右值临时值(12.2)。这个临时对象称为闭包对象。lambda表达式不能出现在未求值的操作数中(第5条)。
[c++ 11, 5.1.2/3] lambda表达式的类型闭包对象的类型)是唯一的、未命名的非联合类类型称为闭包类型,其属性如下所述。这类类型不是聚合(8.5.1)。声明闭包类型在最小的块作用域、类作用域或命名空间作用域中包含相应的lambda表达式。
为什么静态初始化器中的lambda不能访问vc++ 2013中类的私有成员?
c++ 11 lambda可以访问我的私有成员。为什么?
为什么不能在lambda中使用私有方法?
我想它应该在类范围内。引用自cppreference(强调我的):
lambda表达式构造一个未命名的右值临时对象的唯一未命名的非联合非聚合类型,称为闭包类型,哪个在最小的块中声明(为了ADL的目的)作用域、类作用域或包含lambda的命名空间作用域表达 .
在S::s_func
的out- line定义中,遇到S::
的时间进入S
的作用域。因此,lambda表达式包含在S
的类作用域中。由于close类型是S
的成员,所以授予S
的private成员访问权限。
- 未在作用域中声明unordered_map
- 有没有一种方法可以在编译时获得作用域类名
- C++quit()函数中可能存在作用域问题
- 未在此作用域OpenCV3.4中声明cvSaveImage
- 全局作用域中函数指针的赋值
- 在类函数中初始化外部作用域变量
- 不同作用域中的静态变量和全局变量
- 是同一作用域的函数部分中的函数调用
- 未在此作用域中声明的函数和变量 (C++)
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 将作用域枚举转换为基础类型
- 表达式必须具有完整或无作用域的枚举图
- 在构造函数中输入对象时C++类成员作用域
- 无法让"std::enable_if"适用于无作用域枚举
- 为什么不能直接引用作用域枚举类成员,而不能为无作用域枚举生成类成员?
- 函数未在作用域中声明 / 如何结合使用 header.h、header.cpp 和 main.cpp?
- 错误:表达式必须具有算术、无作用域枚举或带有运算符重载的指针类型
- C++11 Lambda闭包通过引用涉及一个堆栈变量,该变量离开作用域是允许的,但得到了未定义的行为
- Lambda Capture by Value强制所有作用域对象为常量
- 静态成员初始化器的Lambda作用域