Язык программирования C++ от Страуструпа

Введение операций с помощью параметров шаблонного класса


Возможны ситуации, когда неявность связи между шаблонной функцией 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.



Содержание раздела