Стандартная библиотека определяет набор классов, представляющих арифметические, реляционные и логические операторы. Каждый класс определяет оператор вызова, который применяет одноименный оператор. Например, у класса plus есть оператор вызова функции, который применяет оператор + к паре операндов; класс modulus определяет оператор вызова, применяющий бинарный оператор %; класс equal_to применяет оператор ==; и т.д.
Эти классы являются шаблонами, которым передается один тип. Он определяет тип параметра оператора вызова. Например, класс plus применяет строковый оператор суммы к объектам класса string; у класса plus типом операндов будет int; класс plus применяет оператор + к объектам класса Sales_data; и т.д.:
plus
//
negate
//
//
//
int sum = intAdd(10, 20); //
sum = intNegate(intAdd(10, 20)); //
//
//
sum = intAdd(10, intNegate(10)); //
Эти типы, перечислены в табл. 4.2, определены в заголовке functional.
Таблица 14.2. Библиотечные объекты функций
| Арифметические | Реляционные | Логические |
|---|---|---|
plus | equal_to | logical_and |
minus | not_equal_to | logical_or |
multiplies | greater | logical_not |
divides | greater_equal | |
modulus | less | |
negate | less_equal |
Классы объектов функций, представляющие операторы, зачастую используются для переопределения заданного по умолчанию оператора, используемого алгоритмом. Как уже упоминалось, по умолчанию алгоритмы сортировки используют оператор operator< для сортировки последовательности в порядке возрастания. Для сортировки в порядке убывания можно передать объект типа greater. Этот класс создает оператор вызова, который вызывает оператор "больше" основного типа элемента. Предположим, например, что svec — это вектор типа vector
//
//
sort(svec.begin(), svec.end(), greater
Это сортирует вектор в порядке убывания. Третий аргумент — безымянный объект типа greater. Когда функция sort() сравнит элементы, вместо оператора < типа элемента она применит переданный объект функции greater. Этот объект применит оператор > к элементам типа string.
Одним из важнейших аспектов этих библиотечных объектов функций является то, что библиотека гарантирует их работоспособность с указателями. Помните, что результат сравнения двух несвязанных указателей непредсказуем (см. раздел 3.5.3). Но может понадобиться сортировать вектор указателей на основании их адреса в памяти. Хотя сделать это самостоятельно непросто, вполне можно применить один из библиотечных объектов функции:
vector
//
sort(nameTable.begin(), nameTable.end(),
[](string *a, string *b) { return a < b; });
//
sort(nameTable.begin(), nameTable.end(), less
Стоит также обратить внимание на то, что ассоциативные контейнеры используют для упорядочивания своих элементов объект типа less. В результате можно определить набор (set) указателей или использовать указатель как ключ в карте (map) без необходимости определять тип less самостоятельно.
Упражнение 14.42. Используя библиотечные объекты и адаптеры функций, определите объекты для:
(a) Подсчета количеств значений больше 1024
(b) Поиска первой строки, не равной pooh
(c) Умножения всех значений на 2