Программирование >>  Инициализация объектов класса, структура 

1 ... 156 157 158 [ 159 ] 160 161 162 ... 395


min( int (*)(int(&) [10]) )

конкретизации вызова func() может быть любая из следующих функций:

min( double (*)(double(&)[20]) )

Поскольку однозначно определить аргументы функции func() нельзя, взятие адреса конкретизированного шаблона в таком контексте приводит к ошибке компиляции.

Этого можно избежать, если использовать явное приведение типов для указания типа

int main() {

правильно: с помощью явного приведения указывается тип аргумента func( static cast< double(*)(rad) >(&min) );

аргумента:

Лучше, однако, применять явное задание аргументов шаблона, как будет показано в разделе 10.4.

10.3. Вывод аргументов шаблона А

При вызове шаблона функции типы и значения его аргументов определяются путем исследования типов фактических аргументов функции. Этот процесс называется выводом аргументов шаблона.

template <class Type, int size>

Параметром функции в шаблоне min() является ссылка на массив элементов типа Type:

Type min( Type (&r array)[size] ) { /* ... */ }

template <typename Type, int size>

Type min( Type (&r array)[size] ) { /* ... */ }

typedef int (&rai) [10] ; typedef double (&rad)[20];

void func( int (*)(rai) ); void func( double (*)(rad) );

int main() {

ошибка: как конкретизировать min()? func( &min );

Функция func() перегружена и тип ее параметра не позволяет однозначно определить ни аргумент шаблона Type, ни значение аргумента шаблона size. Результатом



void f( int pval[9] ) {

ошибка: Type (&)[] != int* int jval = min( pval );

так как pval имеет тин int*, а не является l-значением тина массив int .

При выводе аргументов шаблона не принимается во внимание тип значения, возвращаемого конкретизированным шаблоном функции. Например, если вызов min()

double da[8] = { 10.3, 7.2, 14.0, 3.8, 25.7, 6.4, 5.5, 16.8 };

записан так:

int i1 = min( da );

то конкретизированный экземпляр min() имеет параметр типа указатель на массив из восьми double и возвращает значение типа double. Перед инициализацией i1 это значение приводится к типу int. Однако тот факт, что результат вызова min() используется для инициализации объекта типа int, не влияет на вывод аргументов шаблона.

Чтобы процесс такого вывода завершился успешно, тип фактического аргумента функции не обязательно должен совпадать с типом соответствующего формального параметра. Допустим! три вида преобразований тина: трансформация l-значения, преобразование спецификаторов и приведение к базовому классу, конкретизированному из шаблона класса. Рассмотрим последовательно каждое из них.

Напомним, что трансформация l-значения - это либо преобразование l-значения в г-значение, либо преобразование массива в указатель, либо преобразование функции в указатель (все они рассматривались в разделе 9.3). Для иллюстрации влияния такой трансформации на вывод аргументов шаблона рассмотрим функцию min2() c одним параметром шаблона Type и двумя параметрами функции. Первый параметр min2() -это указатель на тин Type*. size теперь не является параметром шаблона, как в определении min() , вместо этого он стал параметром функции, а его значение должно

template <class Type>

перв параметр имеет тип Type Type min2( 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];

return min val;

быть явно передано при вызове:

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



template <class Type>

перв параметр имеет тип const Type* Type min3( const Type* array, int size ) {

...

первым параметром функции типа const Type*:

min3() можно вызвать, передав int* в качестве первого фактического аргумента, как в

int *pi = &ai;

правильно: приведение спецификаторов к типу const int*

следующем примере:

int i = min3( pi, 4 );

Фактический аргумент функции pi имеет тип указатель на int и не совпадает с типом формального параметра const Type*. Однако, поскольку преобразование спецификаторов допустимо, то он приводится к типу const int* еще до вывода аргумента шаблона Type, для которого затем выводится тип int, и шаблон конкретизирует функцию min3(const int*, int) .

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

min2() можно вызвать, передав в качестве первого аргумента массив из четырех int, как

int ai[4] = { 12, 8, 73, 45 };

int main() {

int size = sizeof (ai) / sizeof (ai[0]);

правильно: преобразование массива в указатель min2( ai, size );

в следующем примере:

Фактический аргумент функции ai имеет тип массив из четырех int и не совпадает с типом соответствующего формального параметра Type*. Однако, поскольку преобразование массива в указатель допустимо, то аргумент ai приводится к типу int* еще до вывода аргумента шаблона Type, для которого затем выводится тип int, и шаблон конкретизирует функцию min2(int*, int) .

Преобразование спецификаторов добавляет const или volatile к указателям (такие трансформации также рассматривались в разделе 9.3). Для иллюстрации влияния преобразования спецификаторов на вывод аргументов шаблона рассмотрим min3() с



1 ... 156 157 158 [ 159 ] 160 161 162 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика