Если мы хотим сравнивать элемент с произвольным значением 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. Абстрактная точка зрения на функции-объекты