Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between static constexpr and static inline variables in C++17?

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.

like image 820
fen Avatar asked Jul 19 '17 07:07

fen


People also ask

Is constexpr variable inline?

A static member variable (but not a namespace-scope variable) declared constexpr is implicitly an inline variable.

What is static constexpr?

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.

Is constexpr automatically inline?

Yes ([dcl. constexpr], §7.1. 5/2 in the C++11 standard): "constexpr functions and constexpr constructors are implicitly inline (7.1.

What is the difference between constexpr and const?

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 .


1 Answers

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.

like image 175
StoryTeller - Unslander Monica Avatar answered Oct 04 '22 17:10

StoryTeller - Unslander Monica