2015-09-27 71 views
5

据我所知,你只能初始化静态const成员在他们的声明if they are integral types的同一行。不过,我仍然能够初始化并使用一些静态常量双打:错误的静态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,因为它是一个数字。如预期的那样,Foo3和Foo4甚至不会编译。但是,我不明白为什么Foo1编译和工作正常。这个具体用法是否被接受?是因为一些优化吗? (我试过使用-O1和-O0)

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

+1

添加'pedantic'开关,gcc甚至会抱怨'Foo1'。 http://melpon.org/wandbox/permlink/o35cpEXlgMedfvMT – dyp

回答

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我们看到这条消息:

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由于结果的类型取决于操作数的类型,不取决于你所指定的它来。

更新

这是depreciated extension

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

还有一个更详细的gcc bug report,它讨论扩展的有效性及其周围的其他相关问题。

使用-pedantic本身足以将其转化为错误,有一个gcc bug report that covers that似乎很奇怪。