Разрешены ли переменные шаблона в нескольких единицах перевода и эффективно ли объединены? - PullRequest
0 голосов
/ 03 октября 2018

См. Следующее:

https://en.cppreference.com/w/cpp/language/definition#One_Definition_Rule

http://eel.is/c++draft/basic.def.odr#12

В нем говорится, что множественные определения шаблонов классов, статические члены-данные шаблонов классов, частичные специализации шаблонови т. д. разрешены и будут действовать как единое определение.Отлично ... но нигде не упоминаются шаблоны переменных?

Если у меня в следующих единицах перевода есть следующее:

template<typename T>
T my_data{};

inline void test() {
    my_data<int> = 1;
}

Будет ли каждая единица перевода получит свое собственное определение my_data, что приведет к множеству символов, или все они будут эффективно объединены в одно определение в программе, где вызов test() в одной единице перевода изменит переменную для другой единицы перевода?

Где в стандартеэто упоминание об этом поведении?

1 Ответ

0 голосов
/ 03 октября 2018

В соответствии со стандартом 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...