На тип параметров, которые не представляют типы, налагаются ограничения. В этом случае разрешено использовать только целочисленные типы, указатели и ссылки. Другие типы (например, float) не допускаются. Аргументы, которые передаются параметру, не являющемуся типом, должны содержать либо целочисленную константу, либо указатель или ссылку на глобальную функцию или объект. Таким образом, эти "нетиповые" параметры следует рассматривать как константы, поскольку их значения не могут быть изменены. Например, в теле функции operator[]() следующая инструкция недопустима:
size = 10; // ошибка
Поскольку параметры-"нетипы" обрабатываются как константы, их можно использовать для установки размерности массива, что существенно облегчает жизнь программисту.
Как показывает пример создания безопасного массива, использование "нетиповых" параметров весьма расширяет сферу применения шаблонных классов. И хотя информация, передаваемая через "нетиповой" аргумент, должна быть известна во время компиляции, малость этого ограничения несравнима с достоинствами, предлагаемыми такими параметрами.
Шаблонный класс queue, представленный выше в этой главе, также выиграл бы от применения к нему "нетипового" параметра, задающего размер очереди. В качестве упражнения попробуйте усовершенствовать класс queue самостоятельно.
Шаблонный класс может по умолчанию определять аргумент, соответствующий обобщенному типу. Например, в результате такой template-спецификации
template <class X=int>
class myclass { //...
};
будет использован тип int, если при создании объекта класса myclass отсутствует задание какого-то бы то ни было типа.
Для аргументов, которые не представляют тип в template-спецификации, также разрешается задавать значений по умолчанию. Они используются в случае, если при реализации класса значение для такого аргумента явно не указано. Аргументы по умолчанию для "нетиповых" параметров задаются с помощью синтаксиса, аналогичного используемому при задании аргументов по умолчанию для параметров функций.
Рассмотрим еще одну версию класса безопасного массива, в котором используются аргументы по умолчанию как для типа данных, так и для размера массива.
// Демонстрация использования шаблонных аргументов по умолчанию.
#include <iostream>
#include <cstdlib>
using namespace std;
/* Здесь параметр AType по умолчанию принимает тип int. а параметр size по умолчанию устанавливается равным 10.
*/
template <class AType=int, int size=10>
class atype{
AType a[size]; // Через параметр size передается размер массива.
public:
atype() {
register int i;
for(i=0; i<size; i++) a[i] = i;
}
AType &operator[](int i);
};
// Обеспечение контроля границ для класса atype.
template <class АТуре, int size>
AType &atype<AType, size>::operator[](int i)
{
if( i<0 || i> size-1) {
cout << "\n Значение индекса ";
cout << i << " за пределами границ массива.\n";
exit(1);
}
return a[i];
}
int main()
{
atype<int, 100> intarray; /* 100-элементный массив целых чисел */
atype<double> doublearray; /* 10-элементный массив double-значений (размер массива установлен по умолчанию) */
atype<> defarray; /* 10-элементный массив int-значений (размер и тип int установлены по умолчанию) */
int i;
cout << "Массив целых чисел: ";