Указатель на функцию-член требует вызова экземпляра, и вы передаете только указатель на функцию-член на std::find_if
(на самом деле ваш синтаксис неправильный, поэтому он вообще не работает; правильный синтаксис std::find_if(itBegin, itEnd, &checker::isEven)
, который по-прежнему не работает по причинам, которые я привел).
Функция find_if
ожидает, что она сможет вызывать функцию с использованием одного параметра (объекта для тестирования), но для вызова функции-члена фактически требуется два: указатель экземпляра this
и объект для сравнения.
Перегрузка operator()
позволяет вам одновременно передавать экземпляр и объект функции, потому что теперь они - одно и то же. С указателем на функцию-член вы должны передать две части информации функции, которая ожидает только одну.
Есть способ сделать это, используя std::bind
(для этого требуется заголовок <functional>
):
checker c;
std::find_if(itBegin, itEnd, std::bind(&checker::isEven, &c, std::placeholders::_1));
Если ваш компилятор не поддерживает std::bind
, вы также можете использовать boost::bind
для этого. Хотя в этом нет особого преимущества перед перегрузкой operator()
.
<ч />
Чтобы уточнить немного, std::find_if
ожидает указатель функции, соответствующий сигнатуре bool (*pred)(unsigned int)
или что-то подобное. На самом деле это не обязательно должен быть указатель на функцию, потому что тип предиката связан шаблоном. Все, что ведет себя как bool (*pred)(unsigned int)
, приемлемо, поэтому функторы работают: их можно вызывать с помощью одного параметра и возвращать bool
.
Как уже отмечали другие, тип checker::isEven
равен bool (checker::*pred)(unsigned int)
, который не ведет себя как исходный указатель на функцию, потому что для его вызова требуется экземпляр checker
.
Указатель на функцию-член концептуально может рассматриваться как обычный указатель на функцию, который принимает дополнительный аргумент, указатель this
(например, bool (*pred)(checker*, unsigned int)
). На самом деле вы можете создать оболочку, которая может быть названа таким образом, используя std::mem_fn(&checker::isEven)
(также из <functional>
). Это все равно не поможет, потому что теперь у вас есть функциональный объект, который должен вызываться с двумя параметрами, а не только с одним, что std::find_if
по-прежнему не нравится.
Использование std::bind
обрабатывает указатель на функцию-член так, как если бы она была функцией, принимающей указатель this
в качестве первого аргумента. Аргументы, передаваемые std::bind
, указывают, что первый аргумент всегда должен быть &c
, а второй аргумент должен связываться с первым аргументом вновь возвращаемого функционального объекта. Этот функциональный объект является оберткой, которую можно вызывать с одним аргументом и, следовательно, можно использовать с std::find_if
.
Хотя тип возвращаемого значения std::bind
не указан, вы можете преобразовать его в std::function<bool(unsigned int)>
(в данном конкретном случае), если вам нужно явно обратиться к объекту связанной функции, а не передавать его прямо другой функции, такой как I сделал в моем примере.