имя-типа
Конструкция имя-шаблонного-класса является именем-класса (§R.9).
Класс, который порождается шаблоном типа для класса, называется шаблонным классом и эквивалентен обычному классу, определенному со специальным именем - именем-шаблонного-класса, см. §R.14.5.
Если в конструкции имя-шаблонного-класса имя-шаблона-типа не определено,то она обозначает неопределенный класс.
Имя шаблонного класса должно быть уникальным в программе и в своей области видимости оно не может обозначать другой шаблон типа, класс, функцию, объект, значение или тип.
Типы, указанные в списке-парам-шаблона-типа из имени-шаблонного-класса, должны соответствовать типам, заданным в списке-параметров-шаблона-типа из шаблона-типа. (Можно сказать, что первые являются фактическими параметрами шаблона типа, а вторые - формальными.)
Кроме типов в списке-парам-шаблона-типа могут быть: выражения-константы, адреса объектов или функций, подлежащих внешнему связыванию, статические члены классов. Для параметров, не являющихся типами, требуется точное соответствие (§R.13.2).
Приведем примеры использования классов шаблона типа vector:
vector‹int› v1(20);
vector‹complex› v2(30);
typedef vector‹complex› cvec; // cvec становится синонимом
// vector‹complex›
cvec v3(40); // v2 и v3 одного типа
v1[3] = 7;
v2[3] = v3.elem(4) = complex(7,8);
Здесь vector‹int› и vector‹complex› являются шаблонными классами, и их определения берутся по умолчанию из шаблона типа vector.
Поскольку шаблонное-имя-класса является именем-класса, то оно может использоваться там, где допустимо имя-класса, например:
class vector‹Shape*›;
vector‹Window›* current_window;
class svector: public vector‹Shape*› {/*… */};
Определение функции-члена шаблонного класса дано в §R.14.6.
R.14.3 Эквивалентность типов
Две конструкции шаблонное-имя-класса обозначают один и тот же класс, если в них совпадают имена шаблонов типа и значения указанных параметров. Например, в следующих описаниях x и y одного типа, который отличен от типа z:
template‹class E, int size› class buffer;
buffer‹char, 2*512› x;
buffer‹char,1024› y;
buffer‹char,512› z;
Ниже приведены описания, в которых одинаковый тип имеют x2 и x3. Он отличается от типов x1 и x4:
template‹class T, void(*err_fct)()›
class list {/*… */};
list‹int,&error_handler1› x1;
list‹int,&error_handler2› x2;
list‹int,&error_handler2› x3;
list‹char,&error_handler2› x4;
R.14.4 Шаблоны типа для функций
Шаблон типа для функции определяет как будет строиться функция. Например, семейство функций sort можно описать следующим образом:
template‹class T› void sort(vector‹T›);
Шаблон типа для функции порождает неограниченное множество перегруженных функций. Функция, порождаемая шаблоном типа для функций, называется шаблонной функцией. Она эквивалентна функции, в описании которой указан тип, соответствующий шаблону, см. §R.14.5.
При вызове шаблонной функции параметры шаблона типа не задаются явно, вместо этого применяется правило разрешения неопределенности перегруженных функций. Рассмотрим пример:
vector‹complex› cv(100);
vector‹int› ci(200);
void f(vector‹complex›& cv, vector‹int›& ci)
{
sort(cv); // вызывается sort(vector‹complex›)
sort(ci); // вызывается sort(vector‹int›)
}
Шаблонная функция может быть перегружена как обычными, так и шаблонными функциями с тем же именем. Для разрешения неопределенности шаблонных и обычных функций с одним и тем же именем надо последовательно пройти три шага:
[1] Попытаться найти точно сопоставимую вызову (§R.13.2) функцию, и если она найдена, вызвать ее.
[2] Попытаться найти шаблон типа для функций, по которому можно создать точно сопоставимую с рассматриваемым вызовом функцию. Если удалось найти, то вызвать функцию.
[3] Попытаться применить обычное правило разрешения неопределенности перегруженных функций (§R.13.2). Если с его помощью функция найдена, вызвать ее.
Если не найдено сопоставимой функции, вызов является ошибочным.
Если уже на первом шаге найдено более одного кандидата, сопоставимого с данной функцией, то вызов также считается неоднозначным и ошибочным.
Успешное выполнение шага [2] приведет к созданию некоторой шаблонной функции с параметрами (§R.14.5), типы которых точно сопоставятся с типами параметров, указанных в вызове. В этом случае недопустимо расхождение даже за счет тривиальных преобразований (§R.13.2).
Такие же действия применяются для сопоставления типов указателей на функции (§R.13.3).
Читать дальше