Теперь обратимся к преобразованию в базовый класс, конкретизированный из шаблона класса. Вывод аргументов шаблона можно выполнить, если тип формального параметра функции является таким шаблоном, а фактический аргумент – базовый класс, конкретизированный из него. Чтобы проиллюстрировать такое преобразование, рассмотрим новый шаблон функции min4() с параметром типа ArrayType, где Array – это шаблон класса, определенный в разделе 2.5. (В главе 16 шаблоны классов обсуждаются во всех деталях.)

template class Type

class Array { /* ... */ }

template class Type

Type min4( ArrayType array )

{

Type min_val = array[0];

for ( int i = 1; i array.size(); ++i )

if ( array[i] min_val )

min_val = array[i];

return min_val;

}

min4() можно вызвать, передав в качестве первого аргумента ArrayRCint, как показано в следующем примере. (ArrayRC – это шаблон класса, также определенный в главе 2; наследование классов подробно рассматривается в главах 17 и 18.)

template class Type

class ArrayRC : public ArrayType { /* ... */ };

int main() {

ArrayRCint ia_rc(10);

min4( ia_rc );

}

Фактический аргумент ia_rc имеет тип ArrayRCint. Он не совпадает с типом формального параметра ArrayType. Но одним из базовых классов для ArrayRCint является Arrayint, так как он конкретизирован из шаблона класса, указанного в качестве формального параметра функции. Поскольку фактический аргумент является производным классом, то его можно использовать при выводе аргументов шаблона. Таким образом, перед выводом аргумент функции ArrayRCint преобразуется в тип Arrayint, после чего для аргумента шаблона Type выводится тип int и конкретизируется функция min4(Arrayint).

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

template class T T min5( T, T ) { /* ... */ }

unsigned int ui;

int main() {

// ошибка: нельзя конкретизировать min5( unsigned int, int )

// должно быть: min5( unsigned int, unsigned int ) или

// min5( int, int )

min5( ui, 1024 );

}

Оба фактических аргумента функции должны иметь один и тот же тип: либо int, либо unsigned int, поскольку в шаблоне они принадлежат к одному типу T. Аргумент шаблона T, выведенный из первого аргумента функции, – это int. Аргумент же шаблона T, выведенный из второго аргумента функции, – это unsigned int. Поскольку они оказались разными, процесс вывода завершается неудачей и при конкретизации шаблона выдается сообщение об ошибке. (Избежать ее можно, если явно задать аргументы шаблона при вызове функции min5(). В разделе 10.4 мы увидим, как это делается.)

Ограничение на допустимые типы преобразований относится только к тем фактическим параметрам функции, которые принимают участие в выводе аргументов шаблона. К остальным аргументам могут применяться любые трансформации. В следующем шаблоне функции sum() есть два формальных параметра. Фактический аргумент op1 для первого параметра участвует в выводе аргумента Type шаблона, а второй фактический аргумент op2 – нет.

template class Type

Type sum( Type op1, int op2 ) { /* ... */ }

Поэтому при конкретизации шаблона функции sum() его можно подвергать любым трансформациям. (Преобразования типов, применимые к фактическим аргументам функции, описываются в разделе 9.3.) Например:

int ai[] = { ... };

double dd;

int main() {

// конкретизируется sum( int, int )

sum( ai[0], dd );

}

Тип второго фактического аргумента функции dd не соответствует типу формального параметра int. Но это не мешает конкретизировать шаблон функции sum(), поскольку тип второго аргумента фиксирован и не зависит от параметров шаблона. Для этого вызова конкретизируется функция sum(int,int). Аргумент dd приводится к типу int с помощью преобразования целого типа в тип с плавающей точкой.

Таким образом, общий алгоритм вывода аргументов шаблона можно сформулировать следующим образом:

* По очереди исследуется каждый фактический аргумент функции, чтобы выяснить, присутствует ли в соответствующем формальном параметре какой-нибудь параметр шаблона.

Перейти на страницу:

Похожие книги