创建需要指向方法函数的指针的模板谓词类,并随之而来的编译器错误
我正在构建一系列重复大量代码的谓词,因此被更改为基于 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
容器执行搜索并检查 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 中是否有我错过的东西可以在单个类中完成相同的工作?我总是可以将谓词分解为几个更具体的谓词,但我试图避免这种情况。
其次,你能帮我解决编译器错误吗?
I'm building a series of predicates that duplicate lots of code, and so are being changed into a single template function class based on the std::unary_function
. The idea is that my class interface requires methods such as Element_t Element()
and std::string Name()
to be defined, so the predicate template arguments are the object type and a value type to which comparison will be made as follows:
// 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;
}
};
Thus, if I have:
class Atom {
public:
const Element_t& Element() const { return _element; }
const std::string& Name() const { return _name; }
};
I would like to perform a search on a container of Atom
s and check for either the Name
or Element
equality using my template predicate like so:
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));
but compiling this returns the following error on the std::find_if
line:
error: address of overloaded function with no contextual type information
Also, trying to form the same predicate for a check of the Element()
as such:
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);
creates a different error!
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>&)
Firstly, am I reinventing the wheel with this predicate? Is there something in the STL that I've missed that does the same job in a single class? I can always break the predicate down into several more specific ones, but I'm trying to avoid that.
Secondly, can you help me with the compiler errors?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不知道有什么简单的方法可以使用 STL 提供的位来完成此操作。可能有一些聪明的 boost 方法,使用迭代器适配器或 boost::lambda,但我个人不会这样做。
显然,C++0x lambda 将使这一切变得简单。
您的问题是尝试将这样的函数转换
为这样的函数:
如果您将
typedef R (U::*fn_t)();
替换为typedef const R& (U::*fn_t)() const;
那么它应该可以工作。下面的代码避免了这个问题,并且还提供了类型推断,这样您就可以编写
mem_fun_eq(&Atom::Name,atomname)
。它为我编译,尽管我还没有测试过。I don't know of any easy way to do this using the bits provided with the STL. There is probably some clever boost way, using iterator adapters, or boost::lambda, but personally I wouldn't go that way.
Obviously C++0x lambdas will make all this easy.
Your problem is attempting to cast a function like this:
into a function like this:
If you replace your
typedef R (U::*fn_t)();
withtypedef const R& (U::*fn_t)() const;
then it should work.The following avoids this problem and also provides type inference so that you can just write
mem_fun_eq(&Atom::Name, atomname)
. It compiles for me, although I haven't tested it.您是否想过尝试混合使用
mem_fun_ref
或mem_fun
对象来代替成员函数调用?基本上,您调用 mem_fun 来创建一个对象,该对象接受两个参数 T* 和函数
A
的模板参数(如果它有一个(或无效,如果没有)。因此,您可以像这样组合它:编辑:
好吧,这并不完全有效,所以为什么不这样做:
然后使用
bind2nd
Have you thought of trying to mix in a
mem_fun_ref
ormem_fun
object in place of the member function call?Basically, you call on
mem_fun
to create an object that accepts two argumentsT*
and a template argument to the functionA
if it has one (or void if it doesn't). Hence you combine it like so:Edit:
Ok, that's not completely working so why not have:
then use
bind2nd