На этом шаге мы рассмотрим использование шаблонов в библиотеке STL.
Стандартизация базовых возможностей языка и библиотеки STL происходила параллельно. При таком подходе в библиотеке могли применяться усовершенствованные средства языка, а язык выигрывал от опыта реализации библиотеки. Более того, в процессе стандартизации библиотеки часто использовались специальные языковые конструкции, которые еще не поддерживались существующими компиляторами. Современный язык C++ заметно отличается от C++ пятилетней давности. Начиная с этого шага, мы приведем краткий обзор новых возможностей языка.
Практически все составляющие библиотеки STL оформлены в виде шаблонов. Без поддержки шаблонов использовать библиотеку невозможно. Более того, для функционирования библиотеки была нужна поддержка некоторых специальных свойств шаблонов, о которых будет рассказано после краткого обзора.
Шаблонами называются функции или классы, определяемые без указания одного или нескольких типов. При использовании шаблона эти типы передаются в виде аргументов, явно или косвенно. Рассмотрим типичный пример - функцию, которая возвращает большее из двух значений:
template <class T> inline const Т& max (const T& a, const T& b) { // Если a<b, вернуть b: иначе вернуть а. return a < b ? b : a; }
В первой строке Т определяется как произвольный тип данных, который должен передаваться при вызове функции. В качестве имени параметра может использоваться произвольный иденгификатор, но имя Т встречается настолько часто, что почти стало стандартным обозначением. Хотя перед формальным параметром шаблона стоит ключевое слово class, он вовсе не обязан быть классом. Допускается любой тип данных, который поддерживает операции, используемые шаблоном.
По тому же принципу классы "параметризуются" для произвольных типов. Параметризация особенно удобна для контейнерных классов, поскольку она позволяет определять операции с элементами контейнера для произвольного типа элементов. Библиотека STL содержит многочисленные шаблоны контейнеров. Впрочем, шаблоны используются и для других целей. Например, строковые классы параметризуются по типу символов и свойствам кодировки.
Не стоит полагать, что шаблон компилируется только один раз, а в результате компиляции строится код, подходящий для любого типа. В действительности шаблон компилируется для каждого типа или комбинации типов, с которыми он используется. Отсюда следует важная проблема, связанная с практическим применением шаблонов: реализация шаблонной функции должна быть доступна к моменту вызова, чтобы функцию можно было откомпилировать для конкретного типа. Следовательно, в настоящее время единственный переносимый способ использования шаблонов основан на их определении в заголовочных файлах с применением подставляемых (inline) функций.
Полноценная реализация STL должна поддерживать не только шаблоны, но и многие стандартизированные свойства шаблонов. Некоторые из этих свойств рассматриваются в следующих шагах.
На следующем шаге мы рассмотрим нетипизированные параметры шаблонов.