//
template
Объявление шаблона должно включить параметры шаблона:
//
template
template
Подобно параметрам функций, имена параметров шаблона не должны совпадать с таковыми в объявлениях и определениях того же шаблона:
//
//
template
template
//
template
Type calc(const Type& a, const Type& b) { /* ... */ }
Конечно, у каждого объявления и определения шаблона должно быть то же количество и вид (т.е. тип или значение) параметров.
Помните, как в разделах 7.4 и 7.6 использовался оператор области видимости (::
) для обращения к статическим членам и членам типа. В обычном коде (не шаблона) у компилятора есть доступ к определению класса. В результате он знает, является ли имя, к которому обращаются через оператор области видимости, типом или статическим членом. Например, в коде string::size_type
, компилятор имеет определение класса string
и может узнать, что size_type
— это тип.
С учетом того, что Т
является параметром типа шаблона, когда компилятор встретит такой код, как T::mem
, он не будет знать до времени создания экземпляра, является ли mem
типом или статической переменной-членом. Но чтобы обработать шаблон, компилятор должен знать, представляет ли имя тип. Например, если T
является именем параметра типа, то как компилятор воспримет следующий код:
T::size_type * p;
Он должен знать, определяется ли переменная по имени p
или происходит умножение статической переменной-члена по имени size_type
на переменную по имени p
.
По умолчанию язык подразумевает, что имя, к которому обращаются через оператор области видимости, не является типом. В результате, если необходимо использовать тип-член параметра типа шаблона, следует явно указать компилятору, что имя является типом. Для этого используется ключевое слово typename
:
template
typename Т::value_type top(const T& с) {
if (!c.empty())
return c.back();
else
return typename T::value_type();
}
Функция top()
ожидает контейнер в качестве аргумента, она использует ключевое слово typename
для определения своего типа возвращаемого значения и создает инициализированный по умолчанию элемент (см. раздел 7.5.3), чтобы возвратить его, если у контейнера с нет никаких элементов.
typename
, а не class
.
В качестве примера перепишем функцию сравнения, использующую по умолчанию библиотечный шаблонный объект функции less
(см. раздел 14.8.2):
//
//
template
int compare(const T &v1, const T &v2, F f = F()) {
if (f(v1, v2)) return -1;
if (f(v2, v1)) return 1;
return 0;
}
Здесь в шаблон добавлен второй параметр типа, F
, представляющий тип вызываемого объекта (см. раздел 10.3.2), и определен новый параметр функции, f
, который будет связан с вызываемым объектом.