Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are "inlined" static consts not allowed, except ints?

Possible Duplicate
Why can't I have a non-integral static const member in a class?

struct Example
{
    static const int One = 1000; // Legal
    static const short Two = 2000; // Illegal
    static const float Three = 2000.0f; // Illegal
    static const double Four = 3000.0; // Illegal
    static const string Five = "Hello"; // Illegal
};

Is there any reason for which #2, #3, #4 and #5 are illegal?

I think I know the reason for #5: the compiler needs a "real" string object (since it's not a built in type) and cannot mindlessy replace Five with "Hello" as if it was #define Five "Hello". But if that's the case, can't the compiler leave an hint in the .obj files and tell the linker to automatically create one instance of string Five somewhere?

For #3 and #4 and especially #2 (lol!)... I can't really see any possible reason! Floats and doubles are built-in types, just as int is! And short is just a (possibly) shorter integer.


EDIT: I'm using Visual Studio 2008 to compile it. I thought all compilers behaved the same in this case, but apparently g++ compiles that fine (except #5). The errors VS gives for that snippets are:

    error C2864: 'Example::Two' : only static const integral data members can be initialized within a class
    error C2864: 'Example::Three' : only static const integral data members can be initialized within a class
    error C2864: 'Example::Four' : only static const integral data members can be initialized within a class
    error C2864: 'Example::Five' : only static const integral data members can be initialized within a class
like image 530
Thomas Bonini Avatar asked Dec 14 '22 01:12

Thomas Bonini


1 Answers

The int and the short are legal, and if your compiler doesn't allow them then your compiler is bust:

9.4.2/4: ... If the static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression.

I believe that the reason that floats and doubles aren't treated specially as constants in the C++ standard, in the way that integral types are, is that the C++ standard is wary that the arithmetic operations on float and double could be subtly different on the compiling machine, than they are on the machine that executes the code. For the compiler to evaluate a constant expression like (a + b), it needs to get the same answer that the runtime would get.

This isn't so much of an issue with ints - you can emulate integer arithmetic relatively cheaply if it differs. But for the compiler to emulate floating-point hardware on the target device might be very difficult. It might even be impossible, if there are different versions of the chip and the compiler doesn't know which the code will run on. And that's even before you start messing with the IEEE rounding mode. So the standard avoided requiring it, so that it didn't have to define when and how compile-time evaluation can differ from runtime evaluation.

As Brian mentions, C++0x is going to address this with constexpr. If I'm right about the original motivation, then presumably 10 years has been long enough to work through the difficulties in specifying this stuff.

like image 172
Steve Jessop Avatar answered Jan 06 '23 18:01

Steve Jessop