在 C++14 中使用 decltype(auto) 声明静态数据成员
Declaring a Static Data Member with decltype(auto) in C++14
此代码是否符合标准?
class Example {
public:
static int x;
};
decltype(auto) Example::x = 1;
int main(){ return 0; }
Clang 3.9.1 编译成功,但 gcc 6.3.0 失败:error: conflicting declaration 'decltype(auto) Example::x'
C++14 标准 (ISO/IEC 14882:2014),第 7.1.6.4 节,第 5 段(强调我的):
占位符类型还可用于在选择语句 (6.4) 或迭代语句 (6.5) 的条件中声明变量,在新表达式(5.3.4) 的新类型 ID 或类型ID 中的类型说明符 seq中声明变量,在for 范围声明中,以及声明具有大括号或等于初始值设定项的静态数据成员,该初始值设定项出现在类定义的成员规范中 (9.4.2).
(重新)声明严格来说并不在类定义的成员规范内,但我看不出有任何充分的理由禁止它。此外,它还可以看作是命名空间范围内变量(静态数据成员变量)的(重新)声明,这在第 4 段中是允许的:
使用 auto 或 decltype(auto) 声明的变量的类型是从其初始值设定项推导出来的。在块 (6.3)、命名空间范围 (3.3.6) 和 for-init 语句 (6.5.3) 中声明变量时,允许使用此用法。
有一个类似的C++11帖子:为什么C++11"auto"关键字不适用于静态成员? 但是,只有一个答案,然后在评论中开始辩论。此外,在这种情况下,clang 通常更可靠,根据该答案,clang 将是错误的,而 gcc 是正确的。
似乎 gcc 变得混乱,因为它试图从初始化中的右值推断x
的类型,而不是在Example
类中的声明。这可能会导致两种类型之间的不一致,使您看起来像是在定义具有相同名称的新变量。
如果我理解正确,您正在寻找的行为可以通过使用从变量声明显式推断类型的宏来使用符合标准的代码来实现:
#define auto_typed_init(a) decltype(a) a
(...)
auto_typed_init(Example::x) = 2;
但是,我不明白为什么在这种情况下标准偏爱初始值设定项,正如本答案中所解释的那样:为什么 C++11'auto' 关键字不适用于静态成员?
- 将函数参数类型声明为 auto
- 如果使用返回引用的函数初始化"auto"var,为什么它不声明引用类型?
- 在 C++14 中使用 decltype(auto) 声明静态数据成员
- C++:在原型中声明"auto"函数返回类型仍然会导致在扣除错误之前使用"auto&quo
- 声明适用于 auto,但不能显式声明类型?
- auto f = bind(dist<>,gen) 在成员声明C++失败。未被识别为函数
- C++11 外部作用域变量声明为 auto
- 没有声明和初始化的类似闭包的函数(即没有'auto f = make_closure();')
- 如何处理"警告:在参数声明中使用'auto'仅适用于 -fconcepts"
- 使用新的 C++11 语法的 auto 进行函数声明,但使用 auto&并且没有 ->
- 如何使用Auto声明无效指针
- 使用 C++11 auto 关键字声明两个(或多个)变量
- 什么时候应该使用 decltype(x) 而不是 auto 来声明变量的类型
- 为什么"auto"将字符串声明为 const char* 而不是 std::string?
- 添加两个整数,但一个声明为"int",另一个声明为"auto"?
- 使用auto声明变量和使用类型名称之间的区别是什么
- 如何在C++中使用关键字"auto"声明和使用变量?
- 使用auto声明变量,并使用原始文字定义的行为进行初始化
- 无法在VS 14 CTP中使用auto声明lambda:类型为'void'的条件表达式是非法的
- 为什么基类不会在同一"auto"声明中自动推导?