Если мы хотим сравнивать элемент с произвольным значением v, то должны как-то сделать это значение неявным аргументом предиката алгоритма find_if(). Мы могли бы попробовать (выбрав в качестве удобного имени идентификатор v_val).
double v_val; // значение, с которым предикат larger_than_v()
// сравнивает свой аргумент
bool larger_than_v(double x) { return x>v_val; }
void f(list
{
v_val = 31; // устанавливаем переменную v_val равной 31,
// для следующего вызова предиката larger_than_v
list
larger_than_v);
if (p!=v.end()) { /* мы нашли значение, превышающее 31 */ }
v_val = x; // устанавливаем переменную v_val равной x
// для следующего вызова предиката larger_than_v
list
larger_than_v);
if (q!=v.end()) { /* мы нашли значение, превышающее x*/ }
// ...
}
ПОПРОБУЙТЕ
Почему такое использование переменной v вызывает у нас такое отвращение? Назовите по крайней мере три способа, которые приведут к непонятным ошибкам. Назовите три приложения, в которых такие программы особенно недопустимы.
21.4. Объекты-функции
Итак, мы хотим передавать предикат алгоритму find_if() и чтобы этот предикат сравнивал элементы со значением, которое мы зададим как его аргумент. В частности, мы хотим написать примерно такой код:
void f(list
{
list
Larger_than(31));
if (p!=v.end()) { /* мы нашли число, превышающее 31 */ }
list
Larger_than(x));
if (q!=v.end()) { /* мы нашли число, превышающее x */ }
// ...
}
Очевидно, что функция Larger_than должна удовлетворять двум условиям.
• Ее можно вызывать как предикат, например pred(*first).
• Она может хранить значение, например 31 или x, передаваемое при вызове.
class Larger_than {
int v;
public:
Larger_than(int vv) : v(vv) { } // хранит аргумент
bool operator()(int x) const { return x>v; } // сравнение
};
Следует отметить, что это определение представляет собой именно то, что мы требовали от предиката. Теперь осталось понять, как это работает. Написав выражение Larger_than(31), мы (очевидно) создаем объект класса Larger_than, хранящий число 31 в члене v. Рассмотрим пример.
find_if(v.begin(),v.end(),Larger_than(31))
Здесь мы передаем объект Larger_than(31) алгоритму find_if() как параметр с именем pred. Для каждого элемента v алгоритм find_if() осуществляет вызов
pred(*first)
Это активизирует оператор вызова функции, т.е. функцию-член operator(), для объекта-функции с аргументом *first. В результате происходит сравнение значения элемента, т.е. *first, с числом 31.
Мы видим, что вызов функции можно рассматривать как результат работы оператора (), аналогично любому другому оператору. Оператор () называют также () в выражении pred(*first) эквивалентен оператору Larger_than::operator(), точно так же, как оператор [] в выражении v[i] эквивалентен оператору vector::operator[].
21.4.1. Абстрактная точка зрения на функции-объекты