Ответ 1
GCC (и Clang) являются правильными. MSVC будет ошибочно, потому что он неправильно реализует поиск.
Есть, кажется, недоразумение от вашего коллеги. Правила поиска:
- Базовая функция шаблона должна быть объявлена до того, как она вызывается из определения
- Специализированная функция шаблона должна быть объявлена до ее создания
Примечание: эти правила применяются для бесплатных функций, внутри класса не требуется форвардное объявление
Обратите внимание, что поскольку определение также действует как декларация, в вашем примере нет необходимости пересылать объявление версии int
.
Правильный пример:
template <typename T> void foo(T); // declare foo<T>
template <typename T> void bar(T t) { foo(t); }// call foo<T> (dependent context)
template <> void foo<int>(int); // declare specialiaztion foo<int>
void bar(int i) { foo(i); } // instantiate foo<T> with int
// which is the specialization
Если имеется базовый шаблон, это ошибка. Если специализация не объявлена до создания экземпляра, она не будет использоваться, и это может впоследствии означать нарушение правила ODR (если другой экземпляр использует специализацию).
Из стандартного (С++ 0x FDIS):
14.6.4.2
1.. Для вызова функции, который зависит от параметра шаблона, функции-кандидаты обнаруживаются с использованием обычных правил поиска (3.4.1, 3.4.2, 3.4.3), за исключением того, что:
- Для части поиска, использующей поиск неквалифицированного имени (3.4.1) или поиск по квалифицированному имени (3.4.3), найдены только объявления функций из контекста определения шаблона.
- Для части поиска с использованием связанных пространств имен (3.4.2) найдены только объявления функций, найденные либо в контексте определения шаблона, либо в контексте контекста шаблона.
Если имя функции является безусловным-идентификатором и вызов будет плохо сформирован или нашел бы лучше подходит имел поиск в пределах соответствующих пространств имен, рассмотренных все функциональные декларации с внешним связыванием, введенным в этих пространствах имен во всех единицах трансляции, не просто рассматривая те декларации, которые содержатся в контекстах шаблона и контекста экземпляра шаблона, то программа имеет поведение undefined.
Обратите внимание, что указанные параграфы предназначены для регулярных функций.