На этом шаге мы приведем общие сведения о создании пользовательских функций.
Библиотека STL имеет расширяемую архитектуру. Это означает, что программист может создавать собственные функции и алгоритмы для обработки коллекций. Конечно, такие операции тоже должны быть унифицированными, но при объявлении в них действительного итератора необходимо указывать тип контейнера. Чтобы упростить написание унифицированных функций, в каждом контейнерном классе присутствуют внутренние определения вспомогательных типов. Рассмотрим следующий пример:
//PRINT_ELEMENTS() // вывод необязательной строки С optcstr, после которой // выводятся все элементы коллекции coll, // разделенные пробелами. template <class T> inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="") { typename T::const_iterator pos; std::cout << optcstr; for (pos=coll .begin(); pos!=coll.end(); ++pos) { std::cout << *pos << ' '; } std::cout << std::endl; }
В этом примере определяется унифицированная функция для вывода необязательной строки, за которой выводятся все элементы переданного контейнера. В следующем объявлении переменная pos объявляется с типом итератора для контейнера переданного типа:
typename T::const_iterator pos;
Ключевое слово typename указывает, что cons_iterator - тип, а не значение типа Т.
Помимо типов iterator и const_iterator контейнеры предоставляют и другие типы, упрощающие написание унифицированных функций. В частности, они предоставляют тип элементов для выполнения операций с временными копиями элементов.
Необязательный второй аргумент функции PRINT_ELEMENTS представляет собой строковый префикс, выводимый перед содержимым контейнера. Так, функция PRINT_ELEMENTS() позволяет снабжать выходные данные комментариями:
PRINT_ELEMENTS (coll, "ell elements: ");
На следующем шаге мы рассмотрим передачу функций алгоритмам в качестве аргументов.