Многие алгоритмы из стандартной библиотеки принимают унарный предикат с сигнатурой bool (Type & item)
, поэтому прямое предоставление указателя на нестатическую функцию-член не работает. Это кажется довольно ограничительным, учитывая, что такое ограничение можно снять, заменив прямой вызов operator ()
в предикате вызовом std::invoke
. Может быть, предложенный подход имеет какие-то недостатки, которые я упустил из виду?
Примечание. Предполагается, что нестатическая функция-член, упомянутая в этом вопросе, отличается от предиката обычной функции только тем, что ссылка на элемент передается как неявный параметр, а не как явный параметр.
Пример кода (онлайн-компилятор):
#include <array>
#include <algorithm>
#include <iostream>
#include <functional>
#include <cassert>
template<typename TForwardIterator, typename TPredicate> TForwardIterator
my_find_if
(
const TForwardIterator p_items_begin
, const TForwardIterator p_items_end
, TPredicate && predicate
)
{
TForwardIterator p_item(p_items_begin);
// while((p_items_end != p_item) && (!predicate(*p_item)))
while((p_items_end != p_item) && (!::std::invoke(predicate, *p_item)))
{
++p_item;
}
return(p_item);
}
class t_Ticket
{
private: int m_number;
public:
t_Ticket(const int number): m_number(number) {}
public: bool
Is_Lucky(void) const {return(8 == m_number);}
};
int main()
{
::std::array<t_Ticket, 10> tickets{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// using standard library
auto p_ticket1(::std::find_if(tickets.begin(), tickets.end(), [](const t_Ticket & ticket) {return(ticket.Is_Lucky());}));
// still works
auto p_ticket2(my_find_if(tickets.begin(), tickets.end(), [](const t_Ticket & ticket) {return(ticket.Is_Lucky());}));
// same thing, but shorter and not sufferring from potential lambda code duplication
auto p_ticket3(my_find_if(tickets.begin(), tickets.end(), &t_Ticket::Is_Lucky));
// using standard library like this won't compile
//auto p_ticket4(::std::find_if(tickets.begin(), tickets.end(), &t_Ticket::Is_Lucky));
assert(p_ticket1 == p_ticket2);
assert(p_ticket2 == p_ticket3);
return(0);
}
std::mem_fn
. - person Tony Delroy   schedule 11.11.2017bool Is_Lucky(void) const {return(8 == m_number);}
-return
не является функцией. Эти скобки не нужны.return 8 == m_number;
(ИМХО) более идиоматичен. Кроме того,void
для обозначения отсутствия аргументов функции является C-измом - не делайте этого в C++ - подойдет толькоbool Is_Lucky() const
. - person Jesper Juhl   schedule 11.11.2017[](auto&& t) -> t.IsLucky()
? Это лямбда с{return();}
выброшена? - person user7860670   schedule 11.11.2017