Бьерн Страуструп - Язык программирования С++. Главы 5-8
Страница 82. Введение операций с помощью параметров шаблонного класса



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.

 
« Предыдущая статья   Следующая статья »