Вызов алгоритма позволяет легко обойти все ловушки в этом коде:
transform(
data.begin, data.end, // Копируем элементы
data inserter(d, d.begin), //
в d с начала контейнера,
bind2nd(plus<double>,41)); // добавляя к каждому 41
Впрочем,
bind2nd
и
plus
достаточно неудобны. Откровенно говоря, в действительности их мало кто использует, и связано это в первую очередь с плохой удобочитаемостью такого кода (см. рекомендацию 6).
При использовании лямбда-функций, генерирующих для нас функциональные объекты, мы можем написать совсем простой код:
. Рассмотрим простой цикл, который выполняет поиск в
vector<int> v
первого элемента, значение которого находится между
x
и
y
. Он вычисляет итератор, который указывает либо на найденный элемент, либо на
v.end
:
vector<int>::iterator i = v.begin;
for (; i != v.end; ++i)
if (*i > x && *i < y) break;
Вызов алгоритма достаточно проблематичен. При отсутствии лямбда-функций у нас есть два варианта — написание собственного функционального объекта или использование стандартных связывателей. Увы, в последнем случае мы не можем обойтись только стандартными связывателями и должны использовать нестандартный (хотя и достаточно распространенный) адаптер
compose2
, но даже в этом случае код получается совершенно непонятным, так что такой код на практике никто просто не напишет:
Другой вариант, а именно — написание собственного функционального объекта — достаточно жизнеспособен. Он достаточно хорошо выглядит в точке вызова, а главный его недостаток— необходимость написания функционального объекта
BetweenValues
, который визуально удаляет логику из точки вызова:
template<typename T>
class BetweenValues : public unary_function<T, bool> {
При использовании функциональных объектов тело цикла оказывается размещено в некотором месте, удаленном от точки вызова, что затрудняет чтение исходного текста. (Использование простых объектов со стандартными и нестандартными связывателями представляется нереалистичным.)
Лямбда-функции [Boost] решают проблему и надежно работают на современных компиляторах, но они не годятся для более старых компиляторов и могут выдавать большие запутанные сообщения об ошибках при некорректном использовании. Вызов же именованных функций, включая функции-члены, все равно требует синтаксиса с использованием связывателей.