Несмотря на всю простоту и краткость кода, он не запустится! Будет ошибка линковки undefined reference to foo::qwerty.
Как такое возможно, если мы четко определили статическое поле qwerty?
Обратимся к стандарту:
If a non-volatile non-inline const static data member is of integral
or enumeration type, its declaration in the class definition can specify
a brace-or-equal-initializer in which every initializer-clause that is an
assignment-expression is a constant expression.
The member shall still be defined in a namespace scope if it is odr-used
in the program and the namespace scope definition shall not contain an initializer
Мы хоть и можем указывать инициализатор для константного статического интегрального поля, но это скорее что-то типа маркера инициализации. То есть именно с этим инициализатором будет определяться поле.
И этот маркет не является определением! Оно все равно нужно, так как foo::qwerty odr-использована. Один из признаков того, что переменная odr-используется - на нее ссылается ссылка.
Так вот функция std::max принимает константные ссылки на объекты. А передаем мы в нее lvalue. Значит у этого lvalue должен быть существующий адрес, чтобы нормально забиндится на ссылку.
Вот и получается порочная цепочка: чтобы забиндится на ссылку нам нужен адрес -> адрес глобальная переменная получает только если у нее есть определение -> так как мы используем ссылку на статическое поле класса нам нужно его определение -> мы его не предоставили -> получили по рукам от линкера.
Чтобы избежать ошибки можно использовать 3 стратегии:
👉🏿 Честно предоставить определение, согласно стандарту, без инициализатора.
struct foo {
static const int qwerty = 100;
};
const int foo::qwerty;👉🏿 Использовать ключевое слово inline, которое, начиная с С++17, позволяет определять поля внутри описания класса.
struct foo {
inline static const int qwerty = 100;
};👉🏿 Вместо const использовать ключевое слово constexpr. Это фактически сразу делает qwerty компайл тайм константой, которая должна быть инициализирована при объявлении и к которой спокойно можно обращаться в том числе и по ссылке.
struct foo {
static constexpr int qwerty = 100;
};Вот такое тонкое место есть в С++)
Surprise everyone. Stay cool.