Ответ 1
Без inline
он явно указывается как только объявление. Как указано в [class.static.data]/2
Объявление элемента нестандартного статического данных в своем классе определение не является определением и может быть неполным типом другого чем cv void. Определение для статического члена данных, который не является определенные в строке определения класса должны появляться в пространстве имен область, охватывающая определение класса участника.
Обоснование - это, скорее всего, сохранение устаревшего кода в целости и сохранности. Напомним, что мы могли бы инициализировать интегральные константы в самом определении класса, так как навсегда. Но для использования odr все еще требуется определение вне класса в некоторой единицы перевода.
Таким образом, чтобы такие переменные неявно встроены в систему, могут быть проблематичными в существующих кодовых базах. Комитет всегда думает о обратной совместимости при добавлении функций основного языка.
Например, рассмотрите это допустимое определение класса С++ 03:
struct foo {
static const int n = 3;
double bar[n];
};
n
может использоваться как константное выражение для определения степени bar
, и оно не рассматривается как odr-use. В настоящее время мы будем писать его как constexpr
1 однако это все еще актуально. Но могут быть случаи, когда n
нужно было бы использовать odr (представьте, что его адрес занят, или ссылка привязана к нему и т.д.). Их, вероятно, не так много, и, вероятно, не часто, но у некоторых API есть сумасшедшие требования, которые в конечном итоге потребуют этого.
const int foo::n;
появится в некоторой единицы перевода.
Теперь, если static inline int i = 8;
внезапно неявно inline
, определение выше (то есть в существующей базе кода) будет нарушением odr. Теперь ранее хорошо сформированный код плохо сформирован. Поэтому лучше всего разрешить использование только явного inline
здесь, поскольку на самом деле он будет иметь только новый код.
<суб > 1 Можно утверждать, что переменные static constexpr
могут иметь одну и ту же проблему (и все же они неявно встроены). Но исходная формулировка IIRC позволила это изменение без потенциального нарушения существующего кода. Это было по существу уже "inline" всем, кроме имени.
Суб >