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



8.4.1 Простой шаблон типа для глобальной функции

 Начнем с простейшего шаблона для sort():

        template<class T> void sort(Vector<T>&);

        void f(Vector<int>& vi,
               Vector<String>& vc,
               Vector<int>& vi2,
               Vector<char*>& vs)
        {
          sort(vi);      // sort(Vector<int>& v);
          sort(vc);      // sort(Vector<String>& v);
          sort(vi2);     // sort(Vector<int>& v);
          sort(vs);      // sort(Vector<char*>& v);
        }

 Какая именно функция sort() будет вызываться определяется фактическим
 параметром. Программист дает определение шаблона типа для функции,
 а задача системы программирования обеспечить создание правильных
 вариантов функции по шаблону и вызов соответствующего варианта.
 Например, простой шаблон с алгоритмом пузырьковой сортировки можно
 определить так:

        template<class T> void sort(Vector<T>& v)
        /*
           Сортировка элементов в порядке возрастания
           Используется сортировка по методу пузырька
       */
       {
         unsigned n = v.size();

         for (int i=0; i<n-1; i++)
             for (int j=n-1; i<j; j--)
                 if (v[j] < v[j-1]) {  // меняем местами v[j] и v[j-1]
                    T temp = v[j];
                    v[j] = v[j-1];
                    v[j-1] = temp;
                 }
           }

 Советуем сравнить это определение с функцией сортировки с тем же
 алгоритмом из $$4.6.9. Существенное отличие этого варианта в том,
 что вся необходимая информация передается в единственном параметре
 v. Поскольку тип сортируемых элементов известен (из типа фактического
 параметра, можно непосредственно сравнивать элементы, а не передавать
 указатель на производящую сравнение функцию. Кроме того, нет нужды
 возиться с операцией sizeof. Такое решение кажется более красивым
 и к тому же оно более эффективно, чем обычное. Все же оно сталкивается
 с трудностью. Для некоторых типов операция < не определена, а для
 других, например char*, ее определение противоречит тому, что
 требуется в приведенном определении шаблонной функции. (Действительно,
 нам нужно сравнивать не указатели на строки, а сами строки).
 В первом случае попытка создать вариант sort() для таких типов
 закончится неудачей (на что и следует надеяться) , а во втором
 появиться функция, производящая неожиданный результат.
    Чтобы правильно сортировать вектор из элементов char* мы можем
 просто задать самостоятельно подходящее определение функции
 sort(Vector<char*>&):

          void sort(Vector<char*>& v)
          {
            unsigned n = v.size();

            for (int i=0; i<n-1; i++)
               for ( int j=n-1; i<j; j--)
                   if (strcmp(v[j],v[j-1])<0) {
                   // меняем местами v[j] и v[j-1]
                      char* temp = v[j];
                      v[j] = v[j-1];
                      v[j-1] = temp;
                   }
         }

 Поскольку для векторов из указателей на строки пользователь дал
 свое особое определение функции sort(), оно и будет использоваться,
 а создавать для нее определение по шаблону с параметром типа
 Vector<char*>& не нужно. Возможность дать для особо важных или
 "необычных" типов свое определение шаблонной функции дает ценное
 качество гибкости в программировании и может быть важным средством
 доведения программы до оптимальных характеристик.

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