【问题标题】:Wrong static const initialization that compiles and works编译和工作的错误静态常量初始化
【发布时间】:2015-09-27 23:38:31
【问题描述】:

据我所知,您只能在声明 if they are integral types 的同一行中初始化静态 const 成员。但是,我仍然能够初始化和使用一些静态 const 双打:

// compiles and works, values are indeed doubles
struct Foo1{ 
    static const double A=2.5;
    static const double B=3.2;
    static const double C=1.7;
};

// compiles, but values are cast to int
struct Foo2{
    static const int A=2;
    static const int B=3;
    static const double C=B/A; //becomes 1
};

// does not compile, Foo3::B cannot appear in a constant-expression
struct Foo3{ 
    static const int A=2;
    static const double B=3;
    static const double C=A/B; 
};

// does not compile, a cast to a type other than an integral or enumeration
// cannot appear in a constant-expression
struct Foo4{ 
    static const int A=2;
    static const int B=3;
    static const double C=(double)A/B; 
};

Foo2 编译但 Foo2::C 变为 1,因此它可能被视为 int,因为它在数字上是 1。正如预期的那样,Foo3 和 Foo4 甚至都没有编译。但是,我不明白为什么 Foo1 既能编译又能正常工作。是否接受此特定用法?是因为一些优化吗? (我尝试过使用 -O1 和 -O0)

注意:使用 GNU 5.2.0 和 cmake 并将标准设置为 C++98。切换到 C++11 工作正常(也就是说,不编译并要求将这些成员切换到 constexpr)。

【问题讨论】:

标签: c++ gcc compiler-errors


【解决方案1】:

Foo1 的情况确实不符合标准,如果我们使用-std=c++98 -pedantic 构建,gcc 将发出如下警告(see it live):

error: floating-point literal cannot appear in a constant-expression
 static const double A=2.5;
                       ^
warning: ISO C++ forbids initialization of member constant 'Foo1::A' of non-integral type 'const double' [-Wpedantic]

在没有-pedantic 的情况下编译不会产生任何错误或警告 (see it live)

所以这一定是一个扩展,如果我们使用 -std=C++98 -pedantic 使用 clang,我们会看到这条消息:

warning: in-class initializer for static data member of type 'const double' is a GNU extension [-Wgnu-static-float-init]
static const double A=2.5;
                    ^ ~~~

这似乎证实这是一个扩展。

在 C++11 中保留了对浮点的这一限制,以保持与 C++03 的兼容性并鼓励一致地使用 constexpr,请参阅:Constant expression initializer for static class member of type double

Foo2 的情况也是如此并且不取决于您将其分配给什么。

更新

这是depreciated extension

G++ 允许在类定义中使用初始化器声明 const 浮点类型的静态数据成员。该标准仅允许 const 整数类型和 const 枚举类型的静态成员的初始化程序,因此此扩展已被弃用,并将从未来版本中删除。

有一个更详细的gcc bug report 讨论了扩展的有效性和其他相关问题。

使用-pedantic 本身就足以将其变成错误似乎很奇怪,有一个gcc bug report that covers that

【讨论】:

    猜你喜欢
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    相关资源
    最近更新 更多