据我所知,你只能在声明if they are integral types 的同一行初始化静态const成员。但是,我仍然可以初始化并使用一些静态const双精度数:
['bBBbAa', 'bBAa', 'bBCcBbAa', 'bBcCBbAa', 'bBcCaABbAa', 'bBcCaAAa', 'bBcCaACcBbAa', 'bBcCAa', 'bBcCCcBbAa']
Foo2编译,但Foo2 :: C变为1,所以也许它被视为一个int,因为它在数字上是一个。正如预期的那样,Foo3和Foo4甚至都没有编译。但是,我不明白为什么Foo1编译和正常工作。这种具体用法是否被接受?是因为一些优化? (我尝试过使用-O1和-O0)
注意:使用带有cmake的GNU 5.2.0并将标准设置为C ++ 98。切换到C ++ 11工作正常(即,不编译并要求将这些成员切换到constexpr)。
答案 0 :(得分:11)
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
初始化C
被允许作为扩展名也是如此,除法的结果将是 int ,因为结果的类型取决于操作数的类型,并不依赖于您为其分配的内容。
更新
G ++允许使用类定义中的初始化程序声明const浮点类型的静态数据成员。该标准仅允许const整数类型和const枚举类型的静态成员的初始化器,因此不推荐使用此扩展,并将从将来的版本中删除。
有一个更详细的gcc bug report讨论了扩展的有效性及其周围的其他相关问题。
使用-pedantic
本身就足以将其转化为错误似乎很奇怪,有一个gcc bug report that covers that。