Inlining constexpr
In C++17, a constexpr
static data member is implicitly inline
. This means that the static data member has the same address in every translation unit that uses it, and there is no need to provide a separate definition for the data member in a source file.
The following example would produce a linker error pre-C++ 17:
// MyClass.h
class MyClass {
public:
static constexpr int myConstExpr = 42;
};
// main.cpp
#include "MyClass.h"
#include <iostream>
void printAddress(const int *ptr);
int main() {
// Taking the address of myConstExpr, this requires a definition.
printAddress(&MyClass::myConstExpr);
return 0;
}
void printAddress(const int *ptr) {
std::cout << "Address of myConstExpr: " << ptr << std::endl;
}
In this case, the address of MyClass::myConstExpr
is required, so a separate definition is needed in a source file for pre-C++17:
// MyClass.cpp (pre-C++17)
#include "MyClass.h"
// Definition in source file required to avoid linker errors
const int MyClass::myConstExpr;
However, in C++17, the separate definition is not necessary, as the constexpr
static data member is implicitly inlined:
// MyClass.h (C++17)
class MyClass {
public:
// Automatically inlined, no separate definition required
static constexpr int myConstExpr = 42;
};
The following code will not produce a linker error for pre-C++17. This is because the compilier just does a compile time replacement for the line std::cout << "Value of myConstExpr: " << MyClass::myConstExpr << std::endl;
, directly replacing MyClass::myConstExpr
with 42
. There is no addressing involved, hence no linker error.
// MyClass.h
class MyClass {
public:
static constexpr int myConstExpr = 42;
};
// main.cpp
#include "MyClass.h"
#include <iostream>
int main() {
std::cout << "Value of myConstExpr: " << MyClass::myConstExpr << std::endl;
return 0;
}