Ответ 1
До С++ 17 вам нужно было повторно объявить все переменные static
вне класса ровно одной единицей перевода (обычно каждая единица перевода является файлом .cpp
и наоборот), но это необязательно). Как вы указали, С++ 17 вводит переменные-члены класса inline
, а переменные static constexpr
автоматически квалифицируются. Вам не разрешено переопределять переменные inline
вне класса, как вы видели во втором примере, но исключение было сделано для constexpr
, потому что ранее вы были разрешены (и на самом деле необходимы), чтобы сделать это, но синтаксис осуждается.
В [class.static.data] p2 он позволяет использовать этот синтаксис для не-встроенных членов ("Объявление элемента нестационарных статических данных в его определении класса не является определением и может быть неполный тип, отличный от cv void. Определение для статического элемента данных, который не определен встроенным в определении класса должны появиться в области пространства имен, охватывающей определение класса участников. ")
В следующем параграфе стандарт допускает constexpr
объявления за пределами класса и требует их для данных не constexpr
(выделено мной):
Если нестационарный нестационарный элемент
const
статических данных имеет тип интеграла или перечисления, его объявление в определении класса может указывать логический или равный-инициализатор в который каждый оператор-инициализатор, являющийся выражением присваивания, является постоянное выражение (8.20). Член все еще должен быть определен в область пространства имен, если она используется odr (6.2) в программе и определение области пространства имен не должно содержать инициализатор. Встроенный статический элемент данных может быть определен в определении класса и может указывать логический или равный-инициализатор. Если член объявленный спецификаторомconstexpr
, он может быть обновлен в область пространства имен без инициализатора (это использование устарело, см. D.1). Объявления других статических данных не должны указывать скобки или равно-инициализатор.
И heres примечание о ностальгии, D.1 Переобучение статических элементов данных constexpr [des.static_constexpr]:
Для совместимости с предыдущими международными стандартами С++ элемент статических данных constexpr может быть избыточно переоформлен за пределами класс без инициализатора. Это использование устарело. [Пример:
struct A { static constexpr int n = 5; // definition (declaration in C++ 2014) }; constexpr int A::n; // redundant declaration (definition in C++ 2014)
- конец примера]