Читать «Справочное руководство по C++» онлайн - страница 84

Бьярн Страустрап

Такие же действия применяются для сопоставления типов указателей на функции (§R.13.3).

Рассмотрим пример:

template‹class T› T max(T a, T b) { return a›b ? a : b; };

void f(int a, int b, char c, char d)

{

 int m1 = max(a,b); // max(int a, int b)

 char m2 = max(c,d); // max(char c, char b)

 int m3 = max(a,c); // ошибка: нельзя создать max(int,char)

}

Добавив к этому примеру описание

int max(int,int);

можно разрешить неопределенность для третьего вызова, поскольку теперь задана функция, которая после стандартного преобразования char в int, может сопоставиться с вызовом max(a,c).

Определение шаблона типа для функции используется для создания различных вариантов шаблона типа. Для вызова определенного варианта достаточно лишь описания шаблона типа.

Каждый параметр-шаблона-типа, который приведен в списке-параметров-шаблона-типа должен обязательно использоваться при задании типов параметров в шаблоне типа для функции.

template‹class T› T* create(); //ошибка

template‹class T›

void f() {// ошибка

 T a;

 //…

}

Все параметры-шаблона-типа, приведенные в шаблоне типа для функции, должны быть параметрами-типа.

R.14.5 Описания и определения

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

Конструкция имя-шаблонного-класса вводит описание шаблонного класса.

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

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

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

template‹class T› void sort(vector‹T›& v) {/*… */}

void sort(vector‹char*›& v) {/*… */}

Здесь определение функции sort будет использоваться для той функции из семейства sort, которая сопоставляется при вызове с типом параметра vector‹char*›. Для других типов vector будет создаваться соответствующее им определение функции по шаблону типа.

Можно определить класс, который задает шаблонный класс, например:

template‹class T› class stream {/*… */};

class stream‹char› {/*… */};

Здесь описание класса будет использоваться в качестве определения потока символов (stream‹char›). Другие потоки будут управляться с помощью шаблонных функций, создаваемых по шаблону типа для функций.