Ответ 1
Как вы сказали, emplace_back
принимает аргументы по ссылке, поэтому передача base_trait::n
заставляет его использовать odr.
объект используется odr, если его значение считывается (если оно не является константой времени компиляции) или не записывается, его адрес берется или ссылка привязана к нему;
До С++ 17 это означает, что здесь требуется определение base_trait::n
. Но так как С++ 17 изменилось поведение, для constexpr static data member определение вне класса не требуется снова.
Если элемент
non-inline (since C++17)
or a constexpr static data member (since C++11)
используется нестандартно, определение в области пространства имен по-прежнему требуется, но оно не может иметь инициализатор.This definition is deprecated for constexpr data members (since C++17).
Статический элемент данных может быть объявлен как встроенный. Встроенный элемент статических данных может быть определен в определении класса и может указывать инициализатор. Это не требует определения вне класса. (поскольку С++ 17)