Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Справочник по С++.doc
Скачиваний:
49
Добавлен:
02.05.2014
Размер:
995.33 Кб
Скачать

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>). Другие потоки будут управляться с помощью шаблонных функций, создаваемых по шаблону типа для функций. Пока не появится описание шаблона типа для класса, никакие операции, которым требуется определенный класс, не могут быть произведены над шаблонным классом. После этого специальный шаблонный класс будет считаться определенным, причем сразу же перед первым глобальным описанием, использующим его имя.

R.14.6 Функции-члены шаблонов типа

Функция-член шаблонного класса считается неявной шаблонной функцией, а параметры шаблона типа для ее класса - ее шаблонными параметрами. Приведем пример, в котором описаны три шаблона типа для функции: template<class T> class vector { T* v; int sz; public: vector(int); T& operator[](int); T& elem(int i) { return v[i]; } // ... }; Функцию, выполняющую индексацию, можно определить следующим образом: template<class T> T& vector<T>::operator[](int i) { if (i<0 || sz>=i) error("vector: range error"); return v[i]; } Шаблонный параметр для vector<T>::operator[]() будет задаваться тем типом vector, к которому применяется операция индексации. vector<int> v1(20); vector<complex> v2(30); v1[3] = 7; // vector<int>::operator[]() v2[3] = complex(7,8); // vector<complex>::operator[]()

R.14.7 Друзья

Функция-друг для шаблона типа не является неявной шаблонной функцией, например: template<class T> class task { // ... friend void next_time(); friend task<T>* preempt(task<T>*); friend task* prmt(task*); // ошибка // ... }; Здесь функция next_time() становится другом всех классов task, а каждый класс task имеет в качестве друга функцию preempt() c соответствующими типами параметров. Функцию preempt() можно определить как шаблон типа. template<class T> task<T>* preempt(task<T>* t) { /* ... */ } Описание функции prmt() является ошибочным, поскольку типа task не существует, а есть только специальные шаблонные типы task<int>, task<record>, и т.д.