// объявления шаблона
template class T class QueueItem;
template class U class QueueItem;
// фактическое определение шаблона
template class Type
class QueueItem { ... };
У параметров могут быть аргументы по умолчанию (это справедливо как для параметров-типов, так и для параметров-констант) - тип или значение, которые используются в том случае, когда при конкретизации шаблона фактический аргумент не указан. В качестве такого аргумента следует выбирать тип или значение, подходящее для большинства конкретизаций. Например, если при конкретизации шаблона класса Buffer не указан размер буфера, то по умолчанию принимается 1024:
template class Type, size = 1024
class Buffer;
В последующих объявлениях шаблона могут быть заданы дополнительные аргументы по умолчанию. Как и в объявлениях функций, если для некоторого параметра задан такой аргумент, то он должен быть задан и для всех параметров, расположенных в списке правее (даже в другом объявлении того же шаблона):
template class Type, size = 1024
class Buffer;
// правильно: рассматриваются аргументы по умолчанию из обоих объявлений
template class Type=string, int size
class Buffer;
(Отметим, что аргументы по умолчанию для параметров шаблонов не поддерживаются в компиляторах, реализованных до принятия стандарта C++. Чтобы примеры из этой книги, в частности из главы 12, компилировались большинством современных компиляторов, мы не использовали такие аргументы.)
Внутри определения шаблона его имя можно применять как спецификатор типа всюду, где допустимо употребление имени обычного класса. Вот более полная версия определения шаблона QueueItem:
template class Type
class QueueItem {
public:
QueueItem( const Type & );
private:
Type item;
QueueItem *next;
};
Обратите внимание, что каждое появление имени QueueItem в определении шаблона - это сокращенная запись для
QueueItemType
Такую сокращенную нотацию можно употреблять только внутри определения QueueItem (и, как мы покажем в следующих разделах, в определениях его членов, которые находятся вне определения шаблона класса). Если QueueItem применяется как спецификатор типа в определении какого-либо другого шаблона, то необходимо задавать полный список параметров. В следующем примере шаблон класса используется в определении шаблона функции display. Здесь за именем шаблона класса QueueItem должны идти параметры, т.е. QueueItemType.
template class Type
void display( QueueItemType &qi )
{
QueueItemType *pqi =
// ...
}
16.1.1. Определения шаблонов классов Queue и QueueItem
Ниже представлено определение шаблона класса Queue. Оно помещено в заголовочный файл Queue.h вместе с определением шаблона QueueItem:
#ifndef QUEUE_H
#define QUEUE_H
// объявление QueueItem
template class T class QueueItem;
template class Type
class Queue {
public:
Queue() : front( 0 ), back ( 0 ) { }
~Queue();
Type& remove();
void add( const Type & );
bool is_empty() const {
return front == 0;
}
private:
QueueItemType *front;
QueueItemType *back;
};
#endif
При использовании имени Queue внутри определения шаблона класса Queue список параметров Type можно опускать. Однако пропуск списка параметров шаблона QueueItem в определении шаблона Queue недопустим. Так, объявление члена front является ошибкой:
template class Type
class Queue {
public:
// ...
private:
// ошибка: список параметров для QueueItem неизвестен
QueueItemType *front;
}
Упражнение 16.1
Найдите ошибочные объявления (или пары объявлений) шаблонов классов:
(a) template class Type
class Container1;
template class Type, int size
class Container1;
(b) template class T, U, class V
class Container2;
(c) template class C1, typename C2
class Container3 {};
(d) template typename myT, class myT
class Container4 {};
(e) template class Type, int *pi
class Container5;
(f) template class Type, int val = 0
class Container6;
template class T = complexdouble, int v
class Container6;
Упражнение 16.2
Следующее определение шаблона List некорректно. Как исправить ошибку?
template class elemenType
class ListItem;
template class elemType
class List {
public:
ListelemType()
: _at_front( 0 ), _at_end( 0 ), _current( 0 ), _size( 0 )