//
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, который будет связан с вызываемым объектом.