Шаблоны
STL – это библиотека шаблонов. Прежде всего вспомним, что такое шаблон. Различают шаблоны функций и шаблоны классов. Шаблон функций (function template) является средством языка C++, позволяющим избежать рутинного переписывания кодов функций, которые имеют сходный алгоритм, но разные типы параметров. Классическим примером, иллюстрирующим выгоды шаблона, является множество реализаций функции max (a, b). При отсутствии механизма шаблонов для придания функции max () универсального характера следует создать несколько функций, разделяющих одно и то же имя. Например:
long max (long a, long b); double max (double a, double b); MyType max (mytype a, mytype b); Vectors max (Vectors a, Vectors b);
Очевидно, что тела всех функций могут выглядеть совершенно одинаково для многих типов параметров. Например, коды функции max могут иметь вид:
return (a>b)? а: b;
В таких случаях удобно использовать шаблон функции. Шаблон задается ключевым словом template:
template <class Т> Т max(Т х, Т у) { return (х>у)? х: у; };
Описатель <class т> – это аргумент шаблона. Символ т (type) означает произвольный тип данных т, который будет задан при использовании шаблона, т выполняет роль формального параметра, поэтому сам символ (т) может быть и другим, но везде одинаковым. При фактическом использовании шаблона место т заменяет какой-то уже описанный тип. Им может быть как стандартный, встроенный тип языка, так и новый тип, определенный пользователем. В том числе он может быть именем класса, определенного ранее. Важно, чтобы для типа был определен смысл операции > (больше). Если т заменяется классом, то в классе должна быть предварительно реализована операция operator > ().
Примечание
Не идите на поводу у ложного друга – переводчика термина operator. В английском языке он имеет смысл операции (например, операция + или операция <, операция логического ИЛИ, и т. д.). То, что мы называем оператором языка (например, оператор while, оператор for, условный оператор if, и т. д.), имеет английский аналог – statement (например, conditional statement if).
Если задан шаблон, то компилятор генерирует подходящие коды функции max () в соответствии с конкретными типами фактических параметров, использованных при вызове функции. Например, встретив во внешней функции коды:
Man a("Alex Black", 54), b("Galina Black", 44), с; с = max (a, b); cout << "\n Старший: " << с;
Компилятор в сгенерированной по шаблону копии функции max при сравнении объектов класса Man использует функцию operator > (), которая должна быть определена внутри класса Man. Например, так:
int operator >(Man& m) { return m__Age > m .m_Age; }
Если в той же внешней функции встретится оператор:
cout << "\n max (10.011) = " << max (10.011);
То компилятор в другой копии функции max, сгенерированной по тому же шаблону, использует операцию >, определенную для стандартного типа данных int. Один раз написав шаблон функции max, мы можем вызывать ее для всех типов данных, для которых определена операция operator > (). Если для какого-то типа данных тело функции max не годится, то можно отменить (override) действие шаблона функции для этого типа. Например, определив функцию:
char* max (char* s, char *t) { return (strcmp (s, t) >0)?s: t; }
Мы отменяем действие шаблона для символьных строк, так как функция, скроенная по шаблону, осуществляла бы ничего не значащее сравнение указателей s и t. При использовании шаблона следует строго соблюдать типы параметров и не надеяться на стандартные преобразования типов, по умолчанию осуществляемые компилятором при вызове обычных функций. Например, явно заданную функцию, скрывающую (отменяющую) шаблон:
double max (double, double);
Можно вызывать с аргументами (int, double) или (float, long). Компилятор при этом автоматически преобразует параметры к типу double. Однако если явная декларация функции, скрывающей шаблон, отсутствует, то шаблон:
template <class T> T max(Т х, Т у)
Не позволит смешивать типы при вызове функции max. Таким образом, обращение int i=max (9, 8.); вызывает сообщение об ошибке: "Could not find a match for max (int, double) ", которое означает, что не найдена функция max () для пары аргументов типа (int, double).