На этом шаге мы рассмотрим функциональные адаптеры и их использование.
Функциональным адаптером называется объект, который позволяет комбинировать объекты функций друг с другом,
с определенными значениями или со специальными функциями. Функциональные адаптеры тоже объявляются
в заголовочном файле <functional>. Например, в следующей команде выражение
bind2nd(greater(),42) создает комбинированный объект функции для проверки условия "целое число
больше 42":
find_if (coll.begin(),coll.end(), // Интервал bind2nd(greater<int>(),42)) // Критерий
Фактически bind2nd() преобразует бинарный объект функции (например, greater<>) в унарный
объект функции. Второй параметр всегда используется в качестве второго аргумента бинарной функции, передаваемой
в первом параметре. Следовательно, в приведенном примере greater<> всегда вызывается со вторым
аргументом, равным 42.
В таблице 1 перечислены классы стандартных функциональных адаптеров, входящих в стандартную библиотеку C++.
Таблица 1. Стандартные функциональные адаптеры
Выражение | Описание |
---|---|
bind1st(op,value) | op(value,param) |
bind2nd(op,value) | op(value,param) |
not1(op) | !op(param) |
not2(op) | !op(param1,param2) |
Функциональные адаптеры сами по себе являются объектами функций, поэтому их можно объединять с другими
адаптерами и объектами функций для построения более мощных (и более сложных) выражений. Например, следующая
команда находит первый четный элемент коллекции:
pos = find_if (coll.begin(), coll.end(), // Интервал not1(bind2nd(modulus<int>(),2))); // Критерий
В этой команде выражение bind2nd(modulus(),2) возвращает 1 для нечетных значений. Следовательно, оно
может использоваться в качестве критерия для нахождения первого нечетного элемента, потому что значение 1
эквивалентно true. Адаптер not1() производит логическую инверсию результата, поэтому вся команда
ищет первый элемент с четным значением.
Объединяя объекты функций при помощи функциональных адаптеров, можно строить достаточно сложные выражения.
Подобный стиль программирования называется функциональной композицией. Тем не менее в
стандартной библиотеке C++ отсутствуют некоторые адаптеры, которые были бы весьма удобны при
композиции. Например, отсутствуют адаптеры для связывания двух предикатов по условиям "и"/"или" (например,
"больше 4 и меньше 7"). Расширения стандартных функциональных адаптеров делают механизм композиции
гораздо более мощным. Примеры таких расширений мы рассмотрим позднее.
На следующем шаге мы рассмотрим функциональные адаптеры для функций классов.