Я строю серию предикатов, которые дублируют много кода, и поэтому меняются в единый класс функций шаблона на основе std::unary_function
. Идея состоит в том, что мой интерфейс класса требует определения таких методов, как Element_t Element()
и std::string Name()
, поэтому аргументы шаблона предиката - это тип объекта и тип значения, с которым будет производиться сравнение следующим образом:
// generic predicate for comparing an attribute of object pointers to a specified test value
template <class U, typename R>
class mem_fun_eq : public std::unary_function <U*, bool> {
private:
typedef R (U::*fn_t)();
fn_t fn;
R val;
public:
explicit mem_fun_eq (fn_t f, R& r) : fn(f), val(r) { }
bool operator() (U * u) const {
return (u->*fn)() == val;
}
};
Таким образом, если у меня есть:
class Atom {
public:
const Element_t& Element() const { return _element; }
const std::string& Name() const { return _name; }
};
Я хотел бы выполнить поиск в контейнере Atom
s и проверить равенство Name
или Element
, используя мой шаблонный предикат, например:
typedef std::string (Atom::*fn)() const;
Atom_it it = std::find_if( _atoms.begin(), _atoms.end(), mem_fun_eq <Atom, std::string> ((fn)&Atom::Name, atomname));
, но его компиляция возвращает следующую ошибку в строке std::find_if
:
error: address of overloaded function with no contextual type information
Также, пытаясь сформировать тот же предикат для проверки Element()
как таковой:
typedef Atom::Element_t& (Atom::*fn)() const;
Atom_it it = std::find_if(_atoms.begin(), _atoms.end(), mem_fun_eq <Atom, Atom::Element_t> ((fn)&Atom::Element, elmt);
создает другую ошибку!
error: no matching function for call to ‘mem_fun_eq<Atom, Atom::Element_t>::mem_fun_eq(Atom::Element_t& (Atom::*)()const, const Atom::Element_t&)’
note: candidates are: mem_fun_eq<U, R>::mem_fun_eq(R (U::*)(), R&) [with U = Atom, R = Atom::Element_t]
note: mem_fun_eq<Atom, Atom::Element_t>::mem_fun_eq(const mem_fun_eq<Atom, Atom::Element_t>&)
Во-первых, я заново изобретаю колесо с этим предикатом? Есть ли что-то в STL, что я пропустил, что делает ту же работу в одном классе? Я всегда могу разбить предикат на несколько более конкретных, но я пытаюсь избежать этого.
Во-вторых, можете ли вы мне помочь с ошибками компилятора?