В соответствии со стандартом c ++ 14 [basic.def] / 4 :
Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, котораяиспользуется odr в этой программе вне отклоненного оператора;Диагностика не требуется.
Таким образом, если my_data<T>
используется с одним и тем же аргументом шаблона в нескольких единицах перевода, у вас должно быть нарушение odr (без какой-либо диагностики).inline
переменные появились в c ++ 17 для решения этой проблемы, и именно поэтому type_traits
* _v семейство шаблонов переменных объявлено inline
.
На практике, с Gcc и Clang (по крайней мере,Я не могу проверить другие компиляторы), вы не получите никакого нарушения odr, потому что переменные шаблона имеют «неопределенную связь» (как если бы они были объявлены встроенными).
Вы можете проверить это с помощью nm
.Если вы запустите эту командную строку g++ -c test.cpp -std=c++14 && nm test.o | c++filt | grep my_data
, вы должны увидеть, что my_data<int>
является символом категории u
, что соответствует документации nm
:
Символ является уникальным глобальным символом,Это расширение GNU для стандартного набора привязок символов ELF.Для такого символа динамический компоновщик будет следить за тем, чтобы во всем процессе использовался только один символ с этим именем и типом.
В Основная проблема # 1849 можно прочитать это неясное предложение:
Описание в параграфе 6 6.2 [basic.def.odr] того, когда сущности могут быть многократно объявлены в программе, не обсуждает, но должно обсуждать переменные шаблоны.
Могу поспорить, что если все компиляторы дадут неопределенным связям переменные шаблоны, это может отразиться в будущем пересмотре стандарта.Но сейчас мы должны использовать встроенный спецификатор, как это сделано в stl.