Почему специализация шаблонов должна быть встроена?

Я имею в виду этот ответ:

qaru.site/info/394865/...

Я столкнулся с аналогичной проблемой, связанной с OP цитированного вопроса, с функцией

template<typename T>
void func(T& val);

и его специализация

template<>
void func<mytype>(mytype& val);

привело к ошибке дубликата символов (методы реализованы в файле .tpp, который включен в конец моего заголовка). добавив inline в специализированную функцию, разрешив проблему. Почему?

Ответ 1

Согласно пункту 3.2: 4 в стандарте С++

Каждая программа должна содержать ровно одно определение каждого нестрочного функция или переменная, которая используется в этой программе odr; нет диагностических обязательный. Определение может отображаться явно в программе, оно может можно найти в стандартной или пользовательской библиотеке или (когда соответствующий) он неявно определен (см. 12.1, 12.4 и 12,8). Встроенная функция должна быть определена в каждой единицы перевода, в которой она используется odr.

Это объясняет, почему возникает ошибка времени соединения, когда специализированная функция не объявлена ​​встроенной. Программа будет содержать несколько определений специализированной функции, по одному от каждого модуля, включая .tpp файл, и это нарушает условие из стандарта. При объявлении специализированной функции inline она заставит функцию удовлетворять второй части того же предложения, т.е. Что встроенная функция должна быть определена в каждом модуле с использованием функции.

Если параметризованная функция не специализирована, она подпадает под действие пункта 3.2: 6:

Может быть более одного определения типа класса (раздел 9), тип перечисления (7.2), встроенная функция с внешней связью (7.1.2), шаблон класса (раздел 14), шаблон нестатической функции (14.5.6), статический элемент данных шаблона класса (14.5.1.3), функция-член шаблон класса (14.5.1.1) или специализированную специализацию, для которой некоторые параметры шаблона не указаны (14.7, 14.5.5) в программе при условии, что каждое определение появляется в другой единицы перевода

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

Ответ 2

Ну, если вам нужна стандартная цитата, это закончилось бы в [temp.expl.spec]/12

Явная специализация шаблона функции или переменной inline, только если он объявлен с помощью встроенного спецификатора или определен как удаляется и независимо от того, является ли его функция или переменная шаблон встроен. [Пример:

template<class T> void f(T) { /* ... */ }
template<class T> inline T g(T) { /* ... */ }

template<> inline void f<>(int) { /* ... */ }   // OK: inline
template<> int g<>(int) { /* ... */ }           // OK: not inline 

- конец примера]

Вот почему вы должны это делать. Это независимо, потому что я полагаю, что делать иначе было бы бесполезно ограничительным, как продемонстрировал Йола.

Ответ 3

Это будет работать без встроенного:

file1.h

template<typename T> void func(T& val);
template<> void func<mytype>(mytype& val);

file1.cpp

template<> void func<int>(int& ) {}

Но если вы определяете специализацию шаблона в файле заголовка, вы можете нарушить ODR