With C++17 we get inline variables.
One of the uses for them is to define constant fields in classes.
So what's the difference between these two constant definitions:
class MyClass { static constexpr int myFirstVar = 10; static const inline int mySecondVar = 100; };
Of course constexpr
makes myFirstVar
implicitly inline.
What's the better choice here, to use constexpr
or inline
?
Note: when you don't need constness, then inline
makes it easier. With constexpr
you don't have that choice.
A static member variable (but not a namespace-scope variable) declared constexpr is implicitly an inline variable.
Static specifies the lifetime of the variable. A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.
Yes ([dcl. constexpr], §7.1. 5/2 in the C++11 standard): "constexpr functions and constexpr constructors are implicitly inline (7.1.
The primary difference between const and constexpr variables is that the initialization of a const variable can be deferred until run time. A constexpr variable must be initialized at compile time. All constexpr variables are const .
You don't have to specify an initializer for mySecondVar
at the point of declaration. Nor is the initializer required to be constexpr
itself.
This means that if we attempt to define myFirstVar
like this:
class MyClass { static constexpr int myFirstVar; }; int MyClass::myFirstVar = 1;
Or like this:
#include <cstdlib> class MyClass { static constexpr int myFirstVar = rand(); };
It's ill-formed either way. constexpr
semantics demand it and for a good reason.
The inline
specifier approach allows us to include a static variable definition in the header itself, without the initializer being constexpr
; or if the initializer is fairly complex it doesn't have to be in the class definition itself.
So this is a perfectly valid header in C++17:
#include <cstdlib> class MyClass { static const int mySecondVar; }; inline const int MyClass::mySecondVar = rand();
The standard promises us that all translation units that include the header will see the same value for the variable, even though we won't know what it is until run-time.
It's mostly a library writers tool. Assume your library is header only. Then in the olden days, what were your options if you needed a static constant defined like this?
Well, you could have an object file shipped with your library. It will be compiled from a translation unit that contains just the constant definition. Now the library isn't header-only.
Or you could rely on inline functions instead. The inline variable effect can be achieved with the following:
class MyClass { static inline int mySecondVar(); }; inline int MyClass::mySecondVar() { static const int value = rand(); return value; }
But it's hidden behind a wall of syntax, and masks what is essentially a constant, with a function call operator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With