Бьерн Страуструп - Язык программирования С++. Главы 5-8 Страница 82. Введение операций с помощью параметров шаблонного класса
|
Страница 82 из 88
8.4.5 Введение операций с помощью параметров шаблонного класса Возможны ситуации, когда неявность связи между шаблонной функцией sort() и шаблонным классом Comparator создает трудности. Неявную связь легко упустить из виду и в то же время разобраться в ней может быть непросто. Кроме того, поскольку эта связь "встроена" в функцию sort(), невозможно использовать эту функцию для сортировки векторов одного типа, если операция сравнения рассчитана на другой тип (см. упражнение 3 в $$8.9). Поместив функцию sort() в класс, мы можем явно задавать связь с классом Comparator:
template<class T, class Comp> class Sort { public: static void sort(Vector<T>&); };
Не хочется повторять тип элемента, и это можно не делать, если использовать typedef в шаблоне Comparator:
template<class T> class Comparator { public: typedef T T; // определение Comparator<T>::T static int lessthan(T& a, T& b) { return a < b; } // ... };
В специальном варианте для указателей на строки это определение выглядит так:
class Comparator<char*> { public: typedef char* T; static int lessthan(T a, T b) { return strcmp(a,b) < 0; } // ... };
После этих изменений можно убрать параметр, задающий тип элемента, из класса Sort:
template<class T, class Comp> class Sort { public: static void sort(Vector<T>&); };
Теперь можно использовать сортировку так:
void f(Vector<int>& vi, Vector<String>& vc, Vector<int>& vi2, Vector<char*>& vs) { Sort< int,Comparator<int> >::sort(vi); Sort< String,Comparator<String> >:sort(vc); Sort< int,Comparator<int> >::sort(vi2); Sort< char*,Comparator<char*> >::sort(vs); }
и определить функцию sort() следующим образом:
template<class T, class Comp> void Sort<T,Comp>::sort(Vector<T>& v) { for (int i=0; i<n-1; i++) for (int j=n-1; i<j; j--) if (Comp::lessthan(v[j],v[j-1])) { T temp = v[j]; v[j] = v[j-1]; v[j-1] = temp; } }
Последний вариант ярко демонстрирует как можно соединять в одну программу отдельные ее части. Этот пример можно еще больше упростить, если использовать класс сравнителя (Comp) в качестве единственного параметра шаблона. В этом случае в определениях класса Sort и функции Sort::sort() тип элемента будет обозначаться как Comp::T.
|