Hello,
The following code has compiled fine for me. All of a sudden after using VC8 it fails. But reading up on the error it's a perfectly valid error in the C++ specs. and nothing flaky about VC. The question is, why can integers be static consts but not floats?
class SomeClass {
public:
static const int MAXVEL=10; //ok
static const float FUEL_MAX=60.0; //fails (in VC8 its C2864)
...
};
I guess the other question, is what's the best way round it?
[edit]Fixed it. Apparently I remove the initialiser from the header file:
static const float FUEL_MAX;
Then in my .cpp code add it as:
const float Car::FUEL_MAX(60.0f);
How much of a pedantic f^ck is that! c++ is just stupid sometimes. It should be either all or nothing.
class SomeClass { public: static const int MAXVEL=10; static const float FUEL_MAX; // ... }; const float SomeClass::FUEL_MAX=60.0;
[append]
Bastard; thinking for yourself!
The reason is the same one you can't have global variables in header files. Where will it be initialized? With integers, the compiler can simply hard code the value into the program.
Why can't floats be hard coded? it's just a number.
To you, maybe, but to the processor, it's more complex. Floats aren't quite as complex as objects, but they still have separate instructions for dealing with them (for instance, one can increment (add 1 to) an integer, short, or char, but you can't do that to a float).
Cheers. Now I know 
In the previous version of visual studio (2003) and in the version of GCC I used in devc++ the above worked ok.
[edit]
Actually, what I'm doing is going through the revisions of my code for a tutorial and this (revision 5 of 10) was the first time I added the const float. In the next version and onwards I had actually moved it as the code above mentioned, so I guess I must have upgraded to vc8 at that point and found the error!
It's a quirk of the C++ standard.
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constantinitializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions within its scope. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.
There is no such allowance for non-integral types.
Funny you should say that Bob, you're quoting the exact paragraph I found here:
http://www.thescripts.com/forum/thread263179.html
great minds must think alike 
(or read the same books)
To you, maybe, but to the processor, it's more complex. Floats aren't quite as complex as objects, but they still have separate instructions for dealing with them (for instance, one can increment (add 1 to) an integer, short, or char, but you can't do that to a float).
That, on the other hand, is a problem the compiler-maker has to deal with, not the programmer. The programmer has to deal with the quirk Bob describes, which is kind of a nice gesture towards compiler-makers.
And BTW, C++ does allow floats to be incremented; the fact that the compiler has to translate that into the appropriate instructions is a different story and has nothing to do with the problem at hand.
That, on the other hand, is a problem the compiler-maker has to deal with, not the programmer. The programmer has to deal with the quirk Bob describes, which is kind of a nice gesture towards compiler-makers.
And BTW, C++ does allow floats to be incremented; the fact that the compiler has to translate that into the appropriate instructions is a different story and has nothing to do with the problem at hand.
You misunderstood why I was saying what I did. The reason for his problem not being in the standard may be completely arbitrary, btu in this case it isn't, and I was explaining why the decision to disallow non-integer types to be defined that was was made. The example involving increments was referring to the INC instruction, which doesn't exist for floats.
fld1; faddp st1; (assuming the stack isn't full)
I still don't get it. Surely a float is just another bit pattern?
Surely a float is just another bit pattern?
And by that logic, so is a DivX movie. The different is the amount of work the processor has to undertake to manipulate them.
fld1; faddp st1;
inc [ptr];
Fine, a float is a fixed width bit pattern. Initialising a machine word to hold the floating point representation of 1.0 should be no different to initialising it to hold a two's complement representation 1.
I'll admit, I don't know C++ very well. I thought all these were more-or-less equivalent:
#define FUEL_MAX 60.0 class SomeClass { static const float FUEL_MAX=60.0; } const float SomeClass::FUEL_MAX=60.0;
What's the difference (modulo software engineering issues)?
The first is of course limited in its scope, and if I remember corrently, is a double. The second isn't valid 
Initialising a machine word to hold the floating point representation of 1.0 should be no different to initialising it to hold a two's complement representation 1.
But what if I want to have a static const struct and initialize it in the class? It's a fixed width bit pattern, too. Of course, it could have a constructor, so it would need to be initialized in a specific module. That's why static members need to be initialized outside the class declaration. And then where do the standard makers draw the line? They chose to do it after integers.
[append]
The reason integers are allow, I think, is that one can verbatim copy the constant value directly into the opcodes, and one can't do that with floats or any other data type.
So the answer is, it's an arbitrary choice. Fine.
It is an arbitrary choice; but not totally arbitrary. What happens when you use two different compilers to compile your object files, and then link them together? Will you get the same float value on both? What about the various (potentially different) compiler switches?
You can spec around those issues with integers, but it becomes much more complicated with floats.
Am I way off in thinking that integral static data members are allowed to facilitate simple inlining? I don't see why a non-inlined float value could work with an incompatible compiler... unless the linker is capable of rewriting floats from incompatible object files so they are of the right format?
[edit]
Found a partially satisfactory answer (to me) here:
http://www.thescripts.com/forum/thread141022.html
I would think #defined constants are not 100% compatible with different compilers, as Bob said.
a float is a fixed width bit pattern. Initialising a machine word to hold the floating point representation of 1.0 should be no different to initialising it to hold a two's complement representation 1.
IIRC 1.0 should always be the same for IEEE (except endianness), but the arbitrary number you're adding 1 to will be different. Every time it passes a power of two, the exponent increments and the mantissa moves over as you successively add ones. Same as scientific notation, 1.0e+0 + 1.0e+0 = 2.0e+0, but 1.0e+0 + 1.0e+1 = 1.1e+1.