3

Look at the code below, this const static int num1 = 8; compiles. However, the const static double num2 = 8.8; code gives an error. Their modifiers are all const static, so why does int work, but double and other floating-point types result in an error?

struct S {
    const static int num1 = 8;       // OK
    const static double num2 = 8.8;  // error
};

I've tried some built-in types of C++ and found that

  • integer members such as int, short, long, and char can be defined with const static in the class and directly initialized, while
  • floating-point members such as float and double can not.

This confuses me a lot.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Sleeping
  • 43
  • 5
  • Why same identifier for both?, did you try with different identifier name? – Iron Fist Aug 05 '23 at 12:22
  • 1
    If it matters to your question, `constexpr static double a = 8.8;` is the affordance that was added to the language to support this. `constexpr static inline double a = 8.8;` even better. – Eljay Aug 05 '23 at 12:23
  • 1
    Try `constexpr static double a = 8.8;` Also, this question may be similar to [Static const double in c++](https://stackoverflow.com/questions/2777541/static-const-double-in-c). See [constexpr specifier](https://en.cppreference.com/w/cpp/language/constexpr). – tbxfreeware Aug 05 '23 at 12:25
  • 2
    It is a specific exception for `const`-qualified integral and enumeration types that is there only for historical reasons. If you are using C++17 or later you can ignore it and use either `constexpr` instead of `const` if you want the value to be a compile-time constant or `inline` otherwise and you will be able to initialize any static member this way. – user17732522 Aug 05 '23 at 12:57

3 Answers3

5

float data types are non-integral types, which requires constexpr specifier instead of const :

struct S {
    constexpr static double af = 8.8;
    const static int ai = 8; 
};

The original error message could help you debugging this issue:

error: 'constexpr' needed for in-class initialization of static data member 
'const double myclass::af' of non-integral type
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Iron Fist
  • 10,739
  • 2
  • 18
  • 34
2

I have no idea about "why float-point types can't be initialized in class with const double while other built-in types can", but I can provide other ways to initialize const static members in class:

  1. Instead of writing const double a = 8;, you can write constexpr double a = 8;, the difference between these two can be found here

  2. You can initialize it outside the class like:

    class myclass {
        public:
            const static double a;
    };
    
    const double myclass::a = 8;
    
LiuYuan
  • 127
  • 9
2

Well, as a matter of fact, static const double members can be initialized in the class—if you declare them inline. If the value you want to initialize it to also happens to be a constant expression, then you can declare it constexpr, in which case you do not need to declare it inline because a static constexpr data member is automatically inline.

However, when a static const double member is not inline, then it means that exactly one translation unit is responsible for supplying the definition of that member, and the definition is responsible for the initialization. Because a class definition needs to be #included into every translation unit that wants to access members of that class, it means the declaration of the member inside the class should not be a definition (because that would lead to multiple definitions). As a result, you must provide a single definition of the static member somewhere outside the class, and that single definition is the one that is responsible for initializing it.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312