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

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

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

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

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

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

negate<int> 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. Библиотечные объекты функций

Арифметические Реляционные Логические
plus<Type> equal_to<Type> logical_and<Type>
minus<Type> not_equal_to<Type> logical_or<Type>
multiplies<Type> greater<Type> logical_not<Type>
divides<Type> greater_equal<Type>  
modulus<Type> less<Type>  
negate<Type> less_equal<Type>  

Применение библиотечного объекта функции с алгоритмами.

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

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

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

sort(svec.begin(), svec.end(), greater<string>());

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

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

vector<string *> nameTable; // вектор указателей

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

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

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

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

sort(nameTable.begin(), nameTable.end(), less<string*>());

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

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

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

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

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

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

Упражнение 14.43. Используя библиотечные объекты функций, определите, делимо ли переданное значение типа int на некий элемент в контейнере целых чисел.