Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion about declaration and definition of static const data memebers

Tags:

Scott Meyers writes in Effective Modern C++, Item 30 page 210, that there's

no need to define integral static const data members in classes; declarations alone suffice,

then the sample code is

class Widget {   public:     static const std::size_t MinVals = 28; // MinVals' declaration;     ... }; ...                                        // no defn. for MinVals std::vector<int> widgetData; widgetData.reserve(Widget::MinVals);       // use of MinVals 

I was convinced that static const std::size_t MinVals = 28; is declaration and also a definition, as it is giving a value to MinVals, but the comment seems to claim that's only a declaration; the second comment actually claims there's no definition. The text after the code, indeed reads

MinVals lacks a definition.

Which confirms that static const std::size_t MinVals = 28; is not a definition, so I'm a bit confused.

cppreference doesn't help me much (my bold-italic):

If a static data member of integral or enumeration type is declared const (and not volatile), it can be initialized with an initializer in which every expression is a constant expression, right inside the class definition:

struct X {    const static int n = 1;    const static int m{2}; // since C++11    const static int k; }; const int X::k = 3; 

but first two lines in the class look definitions to me.

The same goes for a following example on cppreference:

struct X {     static const int n = 1;     static constexpr int m = 4; }; const int *p = &X::n, *q = &X::m; // X::n and X::m are odr-used const int X::n;             // … so a definition is necessary constexpr int X::m;         // … (except for X::m in C++17) 

where I'd have said static const int n = 1; is a definition, but it is not, based on the second to last comment.

like image 324
Enlico Avatar asked May 17 '20 18:05

Enlico


People also ask

What is the difference between const and static const?

The const variable is basically used for declaring a constant value that cannot be modified. A static keyword is been used to declare a variable or a method as static. A const keyword is been used to assign a constant or a fixed value to a variable.

What do static and const mean?

“static const” is basically a combination of static(a storage specifier) and const(a type qualifier). The static determines the lifetime and visibility/accessibility of the variable.

Is it static const or const static?

They mean exactly the same thing. You're free to choose whichever you think is easier to read. In C, you should place static at the start, but it's not yet required.

What is const static in C++?

static means the value is shared between all instances of the class and const means it doesn't change.


1 Answers

no need to define integral static const data members in classes; declarations alone suffice,

Declarations alone suffice only if that object is not ODR-used, that is, if a data member is not used in a context that would require its address to exist (like binding to a reference or applying operator &). The presence of an initializer does not equal a definition.

In the example from the book, it's clear that MinVals is not ODR-used, i.e., the compiler can use its value directly, without having to create an object in memory, and so the statement:

widgetData.reserve(Widget::MinVals); 

becomes:

widgetData.reserve(28); 

If, however, in any other place, MinVals were ODR-used, that would make the program ill-formed.

All other examples from cppreference clearly indicate when a value is ODR-used and a definition is required, and when not:

struct X {     const static int n = 1;     const static int m{2}; // since C++11     const static int k; }; const int X::k = 3; 

n and m are declarations with initializers. An attempt to obtain the address of either n or m should fail.

struct X {     static const int n = 1;     static constexpr int m = 4; }; const int *p = &X::n, *q = &X::m; const int X::n; constexpr int X::m; 

Expressions &X::n and &X::m count as ODR-use of n and m, respectively (that is, an address is requested). For a constexpr static data members, a definition was required prior to C++17. From C++17, static constexpr data members are implicitly inline, which means, no out-of-class definition is needed, as they are definitions themselves.

like image 152
Piotr Skotnicki Avatar answered Sep 18 '22 12:09

Piotr Skotnicki