Стандартная библиотека определяет набор классов, представляющих арифметические, реляционные и логические операторы. Каждый класс определяет оператор вызова, который применяет одноименный оператор. Например, у класса plus есть оператор вызова функции, который применяет оператор + к паре операндов; класс modulus определяет оператор вызова, применяющий бинарный оператор %; класс equal_to применяет оператор ==; и т.д.

Эти классы являются шаблонами, которым передается один тип. Он определяет тип параметра оператора вызова. Например, класс plus применяет строковый оператор суммы к объектам класса string; у класса plus типом операндов будет int; класс plus применяет оператор + к объектам класса Sales_data; и т.д.:

plus intAdd;      // объект функции, способный сложить

                       // два значения типа int

negate intNegate; // объект функции, способный изменить знак

                       // значения типа int

// использование оператора intAdd::operator(int, int) для

// сложения чисел 10 и 20

int sum = intAdd(10, 20);        // эквивалент sum = 30

sum = intNegate(intAdd(10, 20)); // эквивалент sum = 30

// использование оператора intNegate::operator(int) для создания

// числа -10 как второго параметра выражения intAdd::operator(int, int)

sum = intAdd(10, intNegate(10)); // sum = 0

Эти типы, перечислены в табл. 4.2, определены в заголовке functional.

Таблица 14.2. Библиотечные объекты функций

АрифметическиеРеляционныеЛогические
plusequal_tological_and
minusnot_equal_tological_or
multipliesgreaterlogical_not
dividesgreater_equal 
modulusless 
negateless_equal 
Применение библиотечного объекта функции с алгоритмами

Классы объектов функций, представляющие операторы, зачастую используются для переопределения заданного по умолчанию оператора, используемого алгоритмом. Как уже упоминалось, по умолчанию алгоритмы сортировки используют оператор operator< для сортировки последовательности в порядке возрастания. Для сортировки в порядке убывания можно передать объект типа greater. Этот класс создает оператор вызова, который вызывает оператор "больше" основного типа элемента. Предположим, например, что svec — это вектор типа vector:

// передает временный объект функции, который применяет

// оператор > к двум строкам

sort(svec.begin(), svec.end(), greater());

Это сортирует вектор в порядке убывания. Третий аргумент — безымянный объект типа greater. Когда функция sort() сравнит элементы, вместо оператора < типа элемента она применит переданный объект функции greater. Этот объект применит оператор > к элементам типа string.

Одним из важнейших аспектов этих библиотечных объектов функций является то, что библиотека гарантирует их работоспособность с указателями. Помните, что результат сравнения двух несвязанных указателей непредсказуем (см. раздел 3.5.3). Но может понадобиться сортировать вектор указателей на основании их адреса в памяти. Хотя сделать это самостоятельно непросто, вполне можно применить один из библиотечных объектов функции:

vector nameTable; // вектор указателей

// ошибка: указатели в nameTable не связаны, результат < непредсказуем

sort(nameTable.begin(), nameTable.end(),

     [](string *a, string *b) { return a < b; });

// ok: библиотека гарантирует, что less для типов указателя определен

sort(nameTable.begin(), nameTable.end(), less());

Стоит также обратить внимание на то, что ассоциативные контейнеры используют для упорядочивания своих элементов объект типа less. В результате можно определить набор (set) указателей или использовать указатель как ключ в карте (map) без необходимости определять тип less самостоятельно.

Упражнения раздела 14.8.2

Упражнение 14.42. Используя библиотечные объекты и адаптеры функций, определите объекты для:

(a) Подсчета количеств значений больше 1024

(b) Поиска первой строки, не равной pooh

(c) Умножения всех значений на 2

Перейти на страницу:

Похожие книги