How is the static const class different from int in float?

I have a class with static const members that I initialize inside the class declaration:

 #include <iostream> class Foo { public: static const int i = 9; static const float f = 2.9999; }; int main() { std::cout << Foo::i << std::endl; std::cout << Foo::f << std::endl; return 0; } 

When compiling with GCC 4.8.2 with the option --std=c++11 it gives this compilation error:

 foo.cpp:7:32: error: 'constexpr' needed for in-class initialization of static data member 'const float Foo::f' of non-integral type [-fpermissive] static const float f = 2.9999; ^ 

As you can see from the message, the error disappears if the line changes to static constexpr float f = 2.9999; .

Why can static initialization of an in-class variable with a floating point be different from integral? Isn't it just a value of a certain size (number of bytes) that is copied (for example, a macro) or refers to the use of a pointer?

Some older answers to similar (not identical) questions on SO indicate that this is because floating point expressions can give different results between the compiled computer and the executing machine (assuming a cross-compilation scenario).

However:

  • the code above assigns a value directly, there is no arithmetic operation that must be performed to calculate the value

  • there may be different results for integral expressions, since the results of its overflow and overflow are not uniquely defined in different architectures.

  • Finally, what magic does constexpr here, what const not? Why constexpr n't constexpr do when const used? I mean, why is another keyword when the following operators work fine as C ++ code outside the class: const int i = 9; const float f = 2.9999; const int i = 9; const float f = 2.9999;

+5
source share
1 answer

This is simply a limitation of the language and one that has been examined by introducing generalized constant expressions.

Since the original C ++, only the static constants of a member of a class of an integral type can be initialized inline; this is the restriction of the same type as for the non-piggy type template parameters. So you can combine these two types:

 struct MyTrait { static const int value = 10; }; template <int N> struct Foo; Foo<MyTrait::value> foo; 

In this use, the static constant is not used odr and no definition is required. I ponder, but I can imagine that such a use was the main intention to allow inline initialization. For all other types, you probably want to have a definition anyway, so you could also put an initializer in the definition.

This, of course, is no excuse, and I believe that the introduction of constexpr seeks to correct this original limitation.

+1
source

Source: https://habr.com/ru/post/1204566/


All Articles