int size() const; // текущий размер
int capacity() const;
void resize(int newsize); // увеличение
void push_back(const char& d);
void reserve(int newalloc);
};
Для класса vector
компилятор генерирует аналог класса vector
, содержащий элементы типа double
(см. раздел 19.2.6), используя соответствующее внутреннее имя, подходящее по смыслу конструкции vector
).
Иногда шаблонный класс называют порождающим типом (type generator). Процесс генерирования типов (классов) с помощью шаблонного класса по заданным шаблонным аргументам называется специализацией (specialization) или конкретизацией шаблона (template instantiation). Например, классы vector
и vector
называются специализациями класса vector
. В простых ситуациях, например при работе с классом vector
, конкретизация не вызывает затруднений. В более общих и запутанных ситуациях конкретизация шаблона очень сильно усложняется. К счастью для пользователей шаблонов, вся эта сложность обрушивается только на разработчика компилятора.
Конкретизация шаблона (генерирование шаблонных специализаций) осуществляется на этапе компиляции или редактирования связей, а не во время выполнения программы.
Естественно, шаблонный класс может иметь функции-члены. Рассмотрим пример.
void fct(vector& v)
{
int n = v.size();
v.push_back("Norah");
// ...
}
При вызове такой функции-члена шаблонного класса компилятор генерирует соответствующую конкретную функцию. Например, когда компилятор видит вызов
v.push_back("Norah"), он генерирует функцию
void vector::push_back(const string& d) { /* ... */ }
используя шаблонное определение
template void vector::push_back(const T& d) { /* ... */ };
Итак, вызову v.push_back("Norah")
соответствует конкретная функция. Иначе говоря, если вам нужна функция с конкретным типом аргумента, компилятор сам напишет ее, основываясь на вашем шаблоне.
Вместо префикса template
можно использовать префикс template
. Эти две конструкции означают одно и то же, но некоторые программисты все же предпочитают использовать ключевое слово typename
, “потому, что оно яснее, и потому, что никто не подумает, что оно запрещает использовать встроенные типы, например тип int
, в качестве шаблонного аргумента”. Мы считаем, что ключевое слово class
уже означает “тип”, поэтому никакой разницы между этими конструкциями нет. Кроме того, слово class
короче.
19.3.2. Обобщенное программирование
Шаблоны — это основа для обобщенного программирования на языке С++. По существу, простейшее определение обобщенного программирования на языке С++ — это программирование с помощью шаблонов. Хотя, конечно, это определение носит слишком упрощенный характер. Не следует давать определения фундаментальных понятий программирования в терминах конструкций языка программирования. Эти конструкции существуют для того, чтобы поддерживать технологии программирования, а не наоборот. Как и большинство широко известных понятий, обобщенное программирование имеет несколько определений. Мы считаем наиболее полезным самое простое из них.
• Обобщенное программирование — это создание кода, работающего с разными типами, заданными в виде аргументов, причем эти типы должны соответствовать специфическим синтаксическим и семантическим требованиям.
Например, элементы вектора должны иметь тип, который можно копировать (с помощью копирующего конструктора и копирующего присваивания). В главах 20-21 будут представлены шаблоны, у которых аргументами являются арифметические операции. Когда мы производим параметризацию класса, мы получаем шаблонный класс (class template), который часто называют также параметризованным типом (parameterized type) или параметризованным классом (parameterized class). Когда мы производим параметризацию функции, мы получаем шаблонную функцию (function template), которую часто называют параметризованной функцией (parameterized function), а иногда алгоритмом (algorithm). По этой причине обобщенное программирование иногда называют алгоритмически ориентированным программированием (algorithm-oriented programming); в этом случае основное внимание при проектировании переносится на алгоритмы, а не на используемые типы.