Как и шаблоны функции, шаблоны класса начинаются с ключевого слова template, за которым следует список параметров шаблона. В определении шаблона класса (и его членов) используются параметры шаблона как знакоместа типов или значений, которые будут подставлены при использовании шаблона:

template class Blob {

public:

 typedef T value_type;

 typedef typename std::vector::size_type size_type;

 // конструкторы

 Blob();

 Blob(std::initializer_list il);

 // количество элементов в Blob

 size_type size() const { return data->size(); }

 bool empty() const { return data->empty(); }

 // добавление и удаление элементов

 void push_back(const T &t) {data->push_back(t);}

 // версия перемещения; см. p. 13.6.3

 void push_back(T &&t) { data->push_back(std::move(t)); }

 void pop_back();

 // доступ к элементу

 T& back();

 Т& operator[](size_type i); // определено в разделе 14.5

private:

 std::shared_ptr> data;

 // выдать сообщение, если data[i] недопустим

 void check(size_type i, const std::string &msg) const;

}

У шаблона Blob есть один параметр типа Т. Он используется везде, где ожидается тип элемента, хранимый классом Blob. Например, тип возвращаемого значения функции доступа к элементам Blob определен как Т&. Когда пользователь создаст экземпляр шаблона Blob, он использует параметр Т для замены конкретным типом аргумента шаблона.

За исключением списка параметров шаблона и использования Т вместо string, этот класс совпадает с тем, что было определено в разделе 12.1.1 и модифицировано в разделе 12.1.6, а также в главах 13 и 14.

Создание экземпляра шаблона класса

Как уже неоднократно упоминалось, при использовании шаблона класса следует предоставить дополнительную информацию. Как можно теперь утверждать, эта дополнительная информация является списком явных аргументов шаблона (explicit template argument), которые привязаны к параметрам шаблона. Компилятор использует эти аргументы для создания специфического экземпляра класса по шаблону.

Например, чтобы определить тип для шаблона Blob, следует предоставить тип элемента:

Blob ia; // пустой Blob

Blob ia2 = {0,1,2,3,4}; // Blob с пятью элементами

Оба объекта, ia и ia2, используют ту же специфическую для типа версию шаблона Blob (т.е. Blob). Из этих определений компилятор создает экземпляр класса, который эквивалентен следующему:

template <> class Blob {

 typedef typename std::vector::size_type size_type;

 Blob();

 Blob(std::initializer_list il);

 // ...

 int& operator[](size_type i);

private:

 std::shared_ptr> data;

 void check (size_type i, const std::string &msg) const;

};

Когда компилятор создает экземпляр класса из шаблона Blob, он переписывает его, заменяя каждый экземпляр параметра T заданным аргументом шаблона, которым в данном случае является int.

Компилятор создает разный класс для каждого заданного типа элемента:

// эти определения создают экземпляр двух разных типов Blob

Blob names;  // Blob содержащий строки

Blob prices; // другой тип элемента

Эти определения привели бы к созданию двух разных экземпляров класса: определение names создает класс Blob, в котором каждое вхождение Т заменено на string. Определение prices создает класс Blob, где Т заменено на double.

При каждом создании экземпляра шаблона класса получается независимый класс. У типа Blob нет никаких отношений с другим типом класса Blob или специальных прав доступа к его членам.

Ссылки на тип шаблона в пределах шаблона

При чтении кода шаблона класса не следует забывать, что имя шаблона класса не является именем самого класса (см. раздел 3.3). Шаблон класса используется для создания экземпляра класса, при этом всегда используются аргументы шаблона.

Перейти на страницу:

Похожие книги