Выбрать главу

Явные объявления конкретизации используются в сочетании с опцией компилятора, которая подавляет неявную конкретизацию шаблонов. Название опции в разных компиляторах различно. Например, в VisualAge for C++ для Windows версии 3.5 фирмы IBM эта опция называется /ft-. Если приложение компилируется с данной опцией, то компилятор предполагает, что шаблоны будут конкретизироваться явно, и не выполняет автоматической конкретизации.

Разумеется, если мы не включили в программу явного объявления конкретизации для некоторого шаблона, но задали опцию /ft-, то при сборке произойдет ошибка из-за того, что функция не была конкретизирована.

Упражнение 10.8

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

Упражнение 10.9

Пусть дано следующее определение шаблона функции sum():

template typename Type

Type sum( Type op1, char op2 );

Как записать явное объявление конкретизации этого шаблона с аргументом типа string?

10.6. Явная специализация шаблона А

Не всегда удается написать шаблон функции, который годился бы для всех возможных типов, с которыми он может быть конкретизирован. В некоторых случаях имеется специальная информация о типе, позволяющая написать более эффективную функцию, чем конкретизированная по шаблону. А иногда общее определение, предоставляемое шаблоном, для некоторого типа просто не работает. Рассмотрим, например, следующее определение шаблона функции max():

// обобщенное определение шаблона

template class T

T max( T t1, T t2 ) {

return ( t1 t2 ? t1 : t2 );

}

Когда этот шаблон конкретизируется с аргументом типа const char*, то обобщенное определение оказывается семантически некорректным, если мы интерпретируем каждый аргумент как строку символов в смысле языка C, а не как указатель на символ. В этом случае необходимо предоставить специализированное определение для конкретизации шаблона.

Явное определение специализации – это такое определение, в котором за ключевым словом template следует пара угловых скобок , а за ними – определение специализированного шаблона. Здесь указывается имя шаблона, аргументы, для которых он специализируется, список параметров функции и ее тело. В следующем примере для max(const char*, const char*) определена явная специализация:

#include cstring

// явная специализация для const char*:

// имеет приоритет над конкретизацией шаблона

// по обобщенному определению

typedef const char *PCC;

template PCC max PCC ( PCC s1, PCC s2 ) {

return ( strcmp( s1, s2 ) 0 ? s1 : s2 );

Поскольку имеется явная специализация, шаблон не будет конкретизирован с типом const char* при вызове в программе функции max(const char*, const char*). При любом обращении к max() с двумя аргументами типа const char* работает специализированное определение. Для любых других обращений функция сначала конкретизируется по обобщенному определению шаблона, а затем вызывается. Вот как это выглядит:

#include iostream

// здесь должно быть определение шаблона функции max()

// и его специализации для аргументов const char*

int main() {

// вызов конкретизированной функции: int max int ( int, int );

int i = max( 10, 5 );

// вызов явной специализации:

// const char* max const char* ( const char*, const char* );

const char *p = max( "hello", "world" );

p endl;

return 0;

}

Можно объявлять явную специализацию шаблона функции, не определяя ее. Например, для функции max(const char*, const char*) она объявляется так:

// объявление явной специализации шаблона функции

template PCC max PCC ( PCC, PCC );

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

// ошибка: неправильные объявления специализации

// отсутствует template

PCC max PCC ( PCC, PCC );

// отсутствует список параметров

template PCC max PCC ;

Однако здесь можно опускать задание аргументов шаблона, если они выводятся из формальных параметров функции:

// правильно: аргумент шаблона const char* выводится из типов параметров

template PCC max( PCC, PCC );

В следующем примере шаблон функции sum() явно специализирован: