const declaration inside the class

A lot of these rules have been changing over time, so it really depends on the version of C++ you are using. Also, some of these may not be technically impossible, but the committee simply decided against them because they might be hard to implement, or are prone to errors. So you might not always get the most satisfying answer on why thing are the way they are.

Lets go over them one by one.

Const Member

class Foo
{
    const int bar = 7;
};

This used to be illegal before C++11. Before that version you were only allowed to initialize static variables in their declaration. If you are still not on C++11, my condolences. More details can be found here.

Static Member

class Foo
{
    static int bar = 7;
};

Another one that changed, but more recently. Before C++17 it was illegal to initialize non const static variables in their declaration. This has to do with the one definition rule. When the header containing this class is included in multiple translation units (.cpp files), which one should be responsible for initializing the value? This is why you have to place the definition somewhere in a single .cpp file.

After C++17 you are allowed to do this:

class Foo
{
    inline static int bar = 7;
};

When you use inline like this it somehow figures out how to only initialize it once. More details can be found here.

Static Const Float Member

class Foo
{
    static const float bar = 7.0f;
};

This has mainly to do with the unpredictability of floats when you run into floating point errors. An example:

class Foo
{
    static const float bar = 0.1f;
};

Since 0.1f is impossible to represent in most floating point implementations, you won't get exactly 0.1f, but only something very close to it. This can then result in different behaviors on different systems that have slightly different implementations, causing your program to run differently depending on the system.

This gets even worse when the value is the result of a calculation, because (a*b)*c is not guaranteed to be the exact same value as a*(b*c), even though it might seem like they are.

But const static floats are still allowed when you define the value outside of the class, so technically it would all still be possible to implement. But the committee never did, probably because it would cause more problems than it would solve. This is also similar to why you are allowed to use integral types as template parameters, but not floats.

template <int i> class Foo {}; // Good
template <float f> class Bar {}; // Bad

However, the committee seems to have changed it's opinion somewhat, since we are now allowed to use floats with constexpr. So it can be done if you write this instead:

class Foo
{
    static constexpr float bar = 7.0f;
};

Conclusion

All of these are actually possible in some form with the right version of C++ and the right syntax. Just keep in mind the potential issues described above, and you should be good to go.

Tags:

C++