Наш класс ilist имеет серьезный недостаток: он может хранить элементы только целого типа. Если бы он мог содержать элементы любого типа– как встроенного, так и определенного пользователем, – то его область применения была бы гораздо шире. Модифицировать ilist для поддержки произвольных типов данных позволяет механизм шаблонов (см. главу 16).
При использовании шаблона вместо параметра подставляется реальный тип данных. Например:
list< string > slist;
создает экземпляр списка, способного содержать объекты типа string, а
list< int > ilist;
создает список, в точности повторяющий наш ilist. С помощью шаблона класса можно обеспечить поддержку произвольных типов данных одним экземпляром кода. Рассмотрим последовательность действий, уделив особое внимание классу list_item.
Определение шаблона класса начинается ключевым словом template, затем следует список параметров в угловых скобках. Параметр представляет собой идентификатор, перед которым стоит ключевое слово class или typename. Например:
template <class elemType>
class list_item;
Эта инструкция объявляет list_item шаблоном класса с единственным параметром-типом. Следующее объявление эквивалентно предыдущему:
template <typename elemType>
class list_item;
Ключевые слова class и typename имеют одинаковое значение, можно использовать любое из них. Более удобное для запоминания typename появилось в стандарте С++ сравнительно недавно и поддерживается еще не всеми компиляторами. Поскольку наши тексты были написаны до появления этого ключевого слова, в них употребляется class. Шаблон класса list_item выглядит так:
template <class elemType>
class list_item {
public:
list_item( elemType value, list_item *item = 0 )
: _value( value ) {
if ( !item )
_next = 0;
else {
_next = item->_next;
item->_next = this;
}
}
elemType value() { return _value; }
list_item* next() { return _next; }