编译和工作的静态const初始化错误

gui*_*nca 5 c++ gcc compiler-errors

据我所知,如果静态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; 
};
Run Code Online (Sandbox Code Playgroud)

Foo2编译,但Foo2 :: C变为1,所以也许它被视为一个int,因为它在数字上是一个.正如预期的那样,Foo3和Foo4甚至都没有编译.但是,我不明白为什么Foo1编译和正常工作.这种具体用法是否被接受?是因为一些优化?(我尝试过使用-O1和-O0)

注意:使用带有cmake的GNU 5.2.0并将标准设置为C++ 98.切换到C++ 11工作正常(即,不编译并要求将这些成员切换到constexpr).

Sha*_*our 11

Foo1案件确实不合格,如果我们建立使用-std=c++98 -pedanticGCC将警告如下(见直播):

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]
Run Code Online (Sandbox Code Playgroud)

编译时-pedantic不会产生任何错误或警告(请参见实时)

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

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;
                    ^ ~~~
Run Code Online (Sandbox Code Playgroud)

这似乎证实了这是一个延伸.

浮点这个限制被保存在C++ 11保持与C++ 03兼容,并鼓励坚持使用constexpr看到:为double类型的类的静态成员常量表达式初始化.

这也是案件Foo2初始化C被允许作为扩展,分工的结果将是INT由于结果的类型取决于操作数的类型,不取决于你所指定的它.

更新

这是折旧的扩展:

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

有一个更详细的gcc bug报告,讨论了扩展的有效性以及它周围的其他相关问题.

看起来奇怪的是,使用-pedantic本身就足以将其转化为错误,有一个gcc bug报告可以解决这个问题.