在C ++中使用decltype(auto)声明静态数据成员14

时间:2017-03-24 13:58:51

标签: c++ c++14 static-members auto decltype

此代码是否符合标准?

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段(强调我的):

  

占位符类型也可用于在 type-specifier-seq <中选择语句(6.4)或迭代语句(6.5)的 condition 中声明变量/ em>在 new-type type-id new-expression (5.3.4)中,在 for-range-declaration 声明一个静态数据成员,其中 brace-or-equal-initializer 出现在 member-specification 类定义(9.4.2)

(re)声明在类定义的成员规范中并不严格,但我认为没有任何理由禁止它。此外,它还可以看作是命名空间作用域中变量(静态数据成员变量)的(重新)声明,这在第4段中是允许的:

  

使用auto或decltype(auto)声明的变量的类型是从其初始化程序推导出来的。在块(6.3),命名空间范围(3.3.6)中的和for-init-statement(6.5.3)中声明变量时,允许使用此方法。

有类似的C ++ 11帖子:Why doesn't the C++11 'auto' keyword work for static members? 但是,只有一个答案,然后在评论中开始辩论。此外,在这种情况下,clang通常更可靠,根据答案,clang会出错并且gcc是正确的。

1 个答案:

答案 0 :(得分:1)

gcc似乎感到困惑,因为它试图在初始化时从右值推断x的类型,而在Example类中尝试声明。这可能导致两种类型之间的不一致,使您看起来好像在定义一个具有相同名称的新变量。

如果我正确理解,可以使用符合标准的代码,通过使用从变量声明中显式推断类型的宏来实现所需的行为:

#define auto_typed_init(a) decltype(a) a

(...)

auto_typed_init(Example::x) = 2;

但是,我不明白为什么在这种情况下标准偏爱初始化方法,如以下答案所述:Why doesn't the C++11 'auto' keyword work for static members?