Правило 3b говорит, что, поскольку вызов неоднозначен, следует рассматривать только обычные функции. Ни одна из них не считается наилучшей из устоявших, так как преобразования типов фактических аргументов одинаково плохи: в обоих случаях для установления соответствия требуется стандартная трансформация. Таким образом, вызов неоднозначен, и компилятор сообщает об ошибке.

Упражнение 10.11

Вернемся к представленному ранее примеру:

template class Type

Type max( Type, Type ) { ... }

double max( double, double );

int main() {

int ival;

double dval;

float fd;

max( 0, ival );

max( 0.25, dval );

max( 0, fd );

}

Добавим в множество объявлений в глобальной области видимости следующую специализацию шаблона функции:

template char maxchar* char, char ) { ... }

Составьте список кандидатов и устоявших функций для каждого вызова max() внутри main().

Предположим, что в main() добавлен следующий вызов:

int main() {

// ...

max( 0, 'j' );

}

В пользу какой функции он будет разрешен? Почему?

Упражнение 10.12

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

int i; unsigned int ui;

char str[24]; int ia[24];

template class T T calc( T*, int );

template class T T calc( T, T );

template chat calc( char*. int );

double calc( double, double );

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

(a) cslc( str, 24 ); (d) calc( i, ui );

(b) calc( is, 24 ); (e) calc( ia, ui );

(c) calc( ia[0], 1 ); (f) calc( i, i );

<p>10.9. Разрешение имен в определениях шаблонов А</p>

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

template typename Type

Type min( Type* array, int size )

{

Type min_val = array[0];

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

if ( array[i] min_val )

min_val = array[i];

print( "Minimum value found: ");

print( min_val );

return min_val;

}

В функции min() типы переменных array и min_val зависят от фактического типа, которым будет заменен Type при конкретизации шаблона, тогда как тип переменной size останется int при любом типе параметра шаблона. Следовательно, типы array и min_val в разных конкретизациях различны. Поэтому мы говорим, что типы этих переменных зависят от параметра шаблона, тогда как тип size от него не зависит.

Так как тип min_val неизвестен, то неизвестна и операция, которая будет использоваться при появлении min_val в выражении. Например, какая функция print() будет вызвана при обращении print(min_val)? С типом аргумента int? Или float? Будет ли вызов ошибочным, поскольку не существует функции, которая может быть вызвана с аргументом того же типа, что и min_val? Принимая все это во внимание, мы говорим, что и вызов print(min_val) зависит от параметра шаблона.

Такие вопросы не возникают для тех конструкций внутри min(), которые не зависят от параметров шаблона. Например, всегда известно, какая функция должна быть вызвана для print( "Minimum value found: "). Это функция печати строк символов. В данном случае print() остается одной и той же при любой конкретизации шаблона, то есть не зависит от его параметров.

В главе 7 мы видели, что в C++ функция должна быть объявлена до ее вызова. Нужно ли объявлять функцию, вызываемую внутри шаблона, до того, как компилятор увидит его определение? Должны ли мы объявить функцию print() в предыдущем примере до определения шаблона min()? Ответ зависит от особенностей имени, на которое мы ссылаемся. Конструкцию, не зависящую от параметров шаблона, следует объявить перед ее использованием в шаблоне. Представленное выше определение шаблона функции min() некорректно. Поскольку вызов

print( "Minimum value found: ");

не зависит от параметров шаблона, то функция print() для печати строк символов должна быть объявлена до использования. Чтобы исправить эту ошибку, можно поместить объявление print() перед определением min():

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

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