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


Задание свойств класса


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

template class T void sort_vector(vectorT vec) { for (int i = 0; i vec.size() -1; i++) for (int j = i; j vec.size(); j++) { if (vec[i] vec[j]) { T tmp = vec[i]; vec[i] = vec[j]; vec[j] = tmp; } } }

Эта функция будет хорошо работать с числами, но если мы захотим использовать ее для массива указателей на строки (char*), то результат будет несколько неожиданный. Сортировка будет выполняться не по значению строк, а по их адресам (операция "меньше" для двух указателей – это сравнение значений этих указателей, т.е. адресов величин, на которые они указывают, а не самих величин). Чтобы исправить данный недостаток, добавим к шаблону второй параметр:

template class T, class Compare void sort_vector(vectorT vec) { for (int i = 0; i vec.size() -1; i++) for (int j = i; j vec.size(); j++) { if (Compare::less(vec[i], vec[j])) { T tmp = vec[i]; vec[i] = vec[j]; vec[j] = tmp; } } }

Класс Compare должен реализовывать статическую функцию less, сравнивающую два значения типа T. Для целых чисел этот класс может выглядеть следующим образом:

class CompareInt { static bool less(int a, int b) { return a b; }; };

Сортировка вектора будет выглядеть так:

vectorint vec; sortint, CompareInt(vec);

Для указателей на байт (строк) можно создать класс

class CompareCharStr { static bool less(char* a, char* b) { return strcmp(a,b) = 0; } };

и, соответственно, сортировать с помощью вызова

vectorchar* svec; sortchar*, CompareCharStr(svec);

Как легко заметить, для всех типов, для которых операция "меньше" имеет нужный нам смысл, можно написать шаблон класса сравнения:

templateclass T Compare { static bool less(T a, T b) { return a b; }; };

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


vectordouble dvec; sortdouble, Comparedouble (dvec);

Чтобы не загромождать запись, воспользуемся возможностью задать значение параметра по умолчанию. Так же, как и для аргументов функций и методов, для параметров шаблона можно определить значения по умолчанию. Окончательный вид функции сортировки будет следующий:

template class T, class C = CompareT void sort_vector(vectorT vec) { for (int i = 0; i vec.size() -1; i++) for (int j = i; j vec.size(); j++) { if (C::less(vec[i], vec[j])) { T tmp = vec[i]; vec[i] = vec[j]; vec[j] = tmp; } } }

Второй параметр шаблона иногда называют параметром-штрих, поскольку он лишь модифицирует поведение класса, который манипулирует типом, определяемым первым параметром.

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