Таким образом, вызов вызываемого объекта g() вызывает вызываемый объект f() с использованием аргументов вызываемого объекта g() для знакомест наряду с аргументами a, b и с. Например, вызов g(X, Y) приводит к вызову f(a, b, Y, с, X).
bind() для переупорядочивания параметровРассмотрим более конкретный пример применения функции bind() для переупорядочивания аргументов. Используем ее для обращения смысла функции isShorter() следующим образом:
//
sort(words.begin(), words.end(), isShorter);
//
sort(words.begin(), words.end(), bind(isShorter, _2, _1));
В первом вызове, когда алгоритм sort() должен сравнить два элемента, А и В, он вызовет функцию isShorter(A, В). Во втором вызове аргументы функции isShorter() меняются местами. В данном случае, когда алгоритм sort() сравнивает элементы, он вызывает функцию isShorter(В, А).
По умолчанию аргументы функции bind(), не являющиеся знакоместами, копируются в возвращаемый ею вызываемый объект. Однако, подобно лямбда-выражениям, иногда необходимо связать аргументы, которые следует передать по ссылке, или необходимо связать аргумент, тип которого не допускает копирования.
Для примера заменим лямбда-выражение, которое захватывало поток ostream по ссылке:
//
//
for_each(words.begin(), words.end(),
[&os, c] (const string &s) { os << s << c; });
Вполне можно написать функцию, выполняющую ту же задачу:
ostream &print(ostream &os, const string &s, char c) {
return os << s << c;
}
Но для замены захвата переменной os нельзя использовать функцию bind() непосредственно:
//
for_each(words.begin(), words.end(), bind(print, os, _1, ' '));
Поскольку функция bind() копирует свои аргументы, она не сможет скопировать поток ostream. Если объект необходимо передать функции bind(), не копируя, то следует использовать библиотечную функцию ref():
for_each(words.begin(), words.end(),
bind(print, ref(os), _1, ' '));
Функция ref() возвращает объект, который содержит переданную ссылку, являясь при этом вполне копируемым. Существует также функция cref(), создающая класс, содержащий ссылку на константу. Подобно функции bind(), функции ref() и cref() определены в заголовке functional.
Прежние версии языка С++ имели много больше ограничений, и все же более сложный набор средств привязки аргументов к функциям. Библиотека определяет две функции — bind1st() и bind2nd(). Подобно функции bind(), эти функции получают функцию и создают новый вызываемый объект для вызова переданной функции с одним из ее параметров, связанным с переданным значением. Но эти функции могут связать только первый или второй параметр соответственно. Поскольку они имеют очень много ограничений, в новом стандарте эти функции bind().
Упражнение 10.22. Перепишите программу подсчета слов размером 6 символов с использованием функций вместо лямбда-выражений.
Упражнение 10.23. Сколько аргументов получает функции bind()?
Упражнение 10.24. Используйте функции bind() и check_size() для поиска первого элемента вектора целых чисел, значение которого больше длины заданного строкового значения.