Так почему бы просто не объявить обычную функцию? Как было показано в разделе 10.3, для преобразования фактического аргумента функции, конкретизированной по шаблону, в соответствующий формальный параметр в случае, когда этот аргумент принимает участие в выводе аргумента шаблона, может быть применено лишь ограниченное множество преобразований типов. Точно так же обстоит дело и в ситуации, когда шаблон функции специализируется явно: к фактическим аргументам функции при этом тоже применимо лишь ограниченное множество преобразований. Явные специализации не помогают обойти соответствующие ограничения. Если мы хотим выйти за их пределы, то должны определить обычную функцию вместо специализации шаблона. (В разделе 10.8 этот вопрос рассматривается более подробно; там же показано, как работает разрешение перегруженной функции для вызова, который соответствует как обычной функции, так и экземпляру, конкретизированному из шаблона.)
Явную специализацию можно объявлять даже тогда, когда специализируемый шаблон объявлен, но не определен. В предыдущем примере шаблон функции sum() лишь объявлен к моменту специализации. Хотя определение шаблона не обязательно, объявление все же требуется. То, что sum() – шаблон, должно быть известно до того, как это имя может быть специализировано.
Такое объявление должно быть видимо до его использования в исходном файле. Например:
#include iostream
#include cstring
// обобщенное определение шаблона
template class T
T max( T t1, T t2 ) { /* ... */ }
int main() {
// конкретизация функции
// const char* max const char* ( const char*, const char* );
const char *p = max( "hello", "world" );
cout "p: " p endl;
return 0;
}
// некорректная программа: явная специализация const char *:
// имеет приоритет над обобщенным определением шаблона
typedef const char *PCC;
template PCC max PCC (PCC s1, PCC s2 ) { /* ... */ }
В предыдущем примере конкретизация max(const char*, const char*) предшествует объявлению явной специализации. Поэтому компилятор имеет право предположить, что функция должна быть конкретизирована по обобщенному определению шаблона. Однако в программе не может одновременно существовать явная специализация и экземпляр, конкретизированный по тому же шаблону с тем же множеством аргументов. Когда в исходном файле после конкретизации встречается явная специализация max(const char*, const char*), компилятор выдает сообщение об ошибке.
Если программа состоит из нескольких файлов, то объявление явной специализации шаблона должно быть видимо в каждом файле, в котором она используется. Не разрешается в одних файлах конкретизировать шаблон функции по обобщенному определению, а в других специализировать с тем же множеством аргументов. Рассмотрим следующий пример:
// --------- max.h -------
// обобщенное определение шаблона
template class Type
Type max( Type t1, Type t2 ) { /* ... */ }
// --------- File1.C -------
#include iostream
#include "max.h"
void another();
int main() {
// конкретизация функции
// const char* max const char* ( const char*, const char* );
const char *p = max( "hello", "world" );
cout "p: " p endl;
another();
return 0;
}
// --------- File2.C -------
#include iostream
#include cstring
#include "max.h"
// явная специализация шаблона для const char*
typedef const char *PCC;
template PCC max PCC ( PCC s1, PCC s2 ) { /* ... */ }
void another() {
// явная специализация
// const char* max const char* ( const char*, const char* );
const char *p = max( "hi", "again" );
cout " p: " p endl;
return 0;
}