Обратные вызовы в C++ | страница 35



>      {

>        int temp = data[j];

>        data[j] = data[j + 1];

>        data[j + 1] = temp;

>      }

>    }

>  }

>}


Описанный код работает с числами. Параметризуем типы (Листинг 32):

Листинг 32. Параметризация типов для сортировки пузырьком

>template                    // (1)

>void sort_bubble(Data* data, size_t size)  // (2)

>{

>  for (size_t i = 0; i < size – 1; i++)

>  {

>    for (size_t j = 0; j < size – i – 1; j++)

>    {

>      if (data[j + 1] < data[j])

>      {

>        Data temp = data[j]; // (3)

>        data[j] = data[j + 1];

>        data[j + 1] = temp;

>      }

>    }

>  }

>}


По сравнению с предыдущим листингом изменений здесь совсем немного: в строке 1 объявлен параметр шаблона для типа данных, в реализации функции вместо типа данных подставляется параметр шаблона (строки 2 и 3). Теперь мы можем делать сортировку для любого типа данных: мы просто вызываем функцию и передаем ей требуемую переменную-массив, а компилятор сгенерирует код для соответствующего массива.

4.3.3. Объявление предикатов

После описанной модификации первоначального кода у нас остается одна проблема: как выполнять операции сравнения для нечисловых данных, например, структур? Ведь алгоритм не знает, да и не должен знать, по каким правилам нужно их сравнивать. Выход очевидный – делегировать эти операции создателю данных. Для этого будем использовать обратный вызов «вычисление по запросу» (п. 1.2.2). Параметрами вызова будут экземпляры данных, а возвращать он будет результат сравнения. Оформленный таким образом вызов называется предикатом.

Предикат – это выражение, принимающее одну или более величину и возвращающее результат булевого типа.

Объявим предикат как дополнительный параметр шаблона (Листинг 33).

Листинг 33. Шаблон с объявлением предиката

>template               // (1)

>void sort_bubble(Data* data, size_t size, Predicate less) // (2)

>{

>  for (size_t i = 0; i < size – 1; i++)

>  {

>    for (size_t j = 0; j < size – i – 1; j++)

>    {

>      if (less (data[j + 1], data[j])) // (3)

>      {

>        Data temp = data[j];

>        data[j] = data[j + 1];

>        data[j + 1] = temp;

>      }

>    }

>  }

>}


По сравнению с предыдущим кодом из Листинг 32 изменения здесь следующие: в объявлении шаблона (строка 1) объявлен дополнительный параметр – предикат, в функции шаблона (строка 2) предикат объявляется как дополнительный входной параметр, в строке 3 вместо операции сравнения происходит вычисление предиката.