Ответ 1
Вам не нужно указывать инициализатор для mySecondVar
в точке объявления. Инициализатор не должен сам constexpr
.
Это означает, что если мы попытаемся определить myFirstVar
следующим образом:
class MyClass {
static constexpr int myFirstVar;
};
int MyClass::myFirstVar = 1;
Или вот так:
#include <cstdlib>
class MyClass {
static constexpr int myFirstVar = rand();
};
Он плохо сформировался в любом случае. constexpr
семантика требует этого и по уважительной причине.
Подход спецификатора inline
позволяет включать определение статической переменной в самом заголовке, без инициализатора constexpr
; или если инициализатор довольно сложный, он не обязательно должен быть в самом определении класса.
Итак, это вполне допустимый заголовок в С++ 17:
#include <cstdlib>
class MyClass {
static const int mySecondVar;
};
inline const int MyClass::mySecondVar = rand();
Стандартная promises нас, что все единицы перевода, содержащие заголовок, будут видеть одно и то же значение для переменной, хотя мы не будем знать, что это такое до выполнения.
В основном это инструмент для библиотек. Предположим, что ваша библиотека - только заголовок. Тогда, в прежние дни, каковы были ваши варианты, если вам нужна статическая константа, определенная так?
Ну, у вас может быть объектный файл, загруженный с вашей библиотекой. Он будет скомпилирован из единицы перевода, содержащей только постоянное определение. Теперь библиотека не только для заголовка.
Или вы можете полагаться на встроенные функции. Встроенный переменный эффект может быть достигнут с помощью следующего:
class MyClass {
static inline int mySecondVar();
};
inline int MyClass::mySecondVar() {
static const int value = rand();
return value;
}
Но он скрыт за стенкой синтаксиса и маскирует то, что по существу является константой, с оператором вызова функции.