Упражнение 10.20. Библиотека определяет алгоритм count_if(). Подобно алгоритму find_if(), он получает пару итераторов, обозначающих исходный диапазон и предикат, применяемый к каждому элементу заданного диапазона. Функция count_if() возвращает количество раз, когда предикат вернул значение true. Используйте алгоритм count_if(), чтобы переписать ту часть программы, которая рассчитывала количество слов длиной больше 6.
Упражнение 10.21. Напишите лямбда-выражение, которое захватывает локальную переменную типа int и осуществляет декремент ее значения, пока оно не достигает 0. Как только значение переменной достигнет 0, декремент переменной прекращается. Лямбда-выражение должно возвратить логическое значение, указывающее, имеет ли захваченная переменная значение 0.
Лямбда-выражения особенно полезны для простых операций, которые не предполагается использовать в более чем одном или двух местах. Если ту же операцию необходимо осуществлять во многих местах, то обычно определяют функцию, а не повторяют то же лямбда-выражение многократно. Аналогично, если операция требует многих операторов, обычно лучше использовать функцию.
Как правило, вместо лямбда-выражения с пустым списком захвата проще использовать функцию. Как уже упоминалось, для упорядочивания вектора по длине слов можно использовать или лямбда-выражение, или нашу функцию isShorter(). Точно так же совсем не сложно заменить лямбда-выражение, выводившее содержимое вектора, функцией, которая получает строку и выводит ее на стандартное устройство вывода.
Однако не так просто написать функцию для замены лямбда-выражений, которые захватывают локальные переменные. Рассмотрим, например, использованное в вызове функции find_if() лямбда-выражение, которое сравнивало размер строки с заданным размером. Совсем не сложно написать функцию, выполняющую те же действия:
bool check_size(const string &s, string::size_type sz) {
return s.size() >= sz;
}
Но мы не можем использовать эту функцию как аргумент функции find_if(). Как уже упоминалось, функция find_if() получает унарный предикат, поэтому переданное ей вызываемое выражение должно получать один аргумент. Лямбда-выражение, переданное функцией biggies() функции find_if(), использует свой список захвата для хранения значения переменной sz. Чтобы использовать функцию check_size() вместо этого лямбда- выражения, следует выяснить, как передать аргумент sz параметру.
bind()check_size() можно решить при помощи новой библиотечной функции bind(), определенной в заголовке functional. Функцию bind() можно считать универсальным адаптером функции (см. раздел 9.6). Она получает вызываемый объект и создает новый вызываемый объект, который адаптирует список параметров исходного объекта.
Общая форма вызова функции bind() такова:
auto
где — это новый вызываемый объект, а — разделяемый запятыми список аргументов, соответствующих параметрам переданного вызываемого объекта . Таким образом, когда происходит вызов объекта , он вызывает , передавая аргументы из списка .
Аргументы из списка список_аргументов могут включать имена в формате _, где — целое число. Эти аргументы — . Они располагаются . Число является позицией параметра вновь созданного вызываемого объекта: _1 — первый параметр, _2 — второй и т.д.
sz к функции check_size()В качестве примера использования функции bind() создадим объект, который вызывает функцию check_size() с фиксированным значением ее параметра размера:
//
//
auto check6 = bind(check_size, _1, 6);