Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static data member initialization in the class definition?

Tags:

c++

I had one question here, so, why (for what?) it is impossible to initialize the static variable inside the class? What I managed

http://eel.is/c++draft/class.static.data#3

If a non-volatile non-inline const static data member is of integral or enumeration type, ... shall still be defined in a namespace scope if it is odr-used in the program and the namespace scope definition shall not contain an initializer.

So, example like this

struct X {
    static int const n = 7; // should be defined outside the class, 
                            // but it's compiles successfully
};

I see this topic https://stackoverflow.com/a/16374286/9780989, there was given such an example

struct s
{
    static std::size_t const len = 10;
    int arr[len];
};
std::size_t const s::len; 

with words that, -

"If len wasn't initialized in the class definition, the compiler couldn't easily know its value in the next line to define the length of arr."

But actually without std::size_t const s::len - this line it's compiles successfully too, so in what cases it shouldn't work? https://gcc.godbolt.org/z/OMKzEO

And so we go further, why we can't initialize static members inside the class, const qualifier allow this, why without we can't do it? What does const do that allows initialization inside a class?

You may said that we can't initialize static members inside the class, because of ODR and that what says Stroustrup:

A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects.

but it's not true, why than compilers resolve the fact that the static member of the template class is initialized in the header (outside the translation unit)?

// templates are completely pushed into headers
template<typename T>
struct X {
    static int val;
};  

// here the static member of the template class is initialized in the header  
template<typename T>
int X<T>::val = 0; 

int main() {
    X<int> x;
}

Okay, I'll try to concretize my questions:

  1. Why const static data members may be defined in the class definition (and if it non odr-used, then it doesn't needed to be defined outside the class)?
  2. Why static data members without const may not be defined in the class definition (see my thoughts about template classes with static members and Stroustrup words about this (does he cheat us?))?

And yes, I see that in C++17 we allow to use inline but I'm less interested in this case.

like image 575
adziri Avatar asked Nov 07 '22 19:11

adziri


1 Answers

why (for what?) it is impossible to initialize the static variable inside the class?

It is not impossible to initialise static variables inside the class definition, if they are const.

But actually without std::size_t const s::len - this line it's compiles successfully too, so in what cases it shouldn't work?

It works because the variable was not odr-used. See [basic.def.odr]:

A variable x whose name appears as a potentially-evaluated expression e is odr-used by e unless

  • x is a reference ...
  • x is a variable of non-reference type that is usable in constant expressions and has no mutable subobjects, and e is an element of the set of potential results of an expression of non-volatile-qualified non-class type to which the lvalue-to-rvalue conversion ([conv.lval]) is applied, or ...

Besides, ODR violations are no diagnostic required. This is technically true for missing definitions. An optimisation might remove odr-uses so that they don't manifest as errors.

Try the following to odr-use the variable:

const int *ptr = &X::n;
  1. Why const static data members may be defined in the class definition?

No. Non-inline const static data members are not defined by the declaration in the class definition. There needs to be a definition (outside the class) if the variable is odr-used.

  1. Why static data members [...] may not be defined in the class definition (see my thoughts about template classes with static members and Stroustrup words about this (does he cheat us?))?

Stroustrup is correct about "complicated linker rules". Those were avoided when it was not possible to define static variables in headers.

Your point about templates makes sense. Those complicated linker rules were needed anyway to make templated static variables possible. And being able to define even non-templated static variables has advantages. These are probably the reasons why the committee chose to allow defining static members in class definition in C++17. See: inline static member definition.

like image 118
eerorika Avatar answered Nov 14 '22 22:11

eerorika