我目前正在开发一个语法分析器类,在代码的某一点上,需要对持有操作符信息的结构进行排序。每个操作符都有一个优先级,这个优先级由用户通过分析器类的公共成员函数来定义。因此,在排序时,我需要我的排序函数根据相应操作符的优先级对元素进行排序。我使用下面的代码来比较元素。
bool parser::op_comp(const op_info& o1, const op_info& o2) {
op_def& op1 = operators[o1.op_char];
op_def& op2 = operators[o2.op_char];
return op1.priority > op2.priority;
}
请注意,我必须把这个函数做成静态的,因为它是定义在一个类里面的。
事实上,我的比较函数比较的元素类型是 op_char
,我从一个包含类型为 op_def
,其中有一个字段 "优先级"。
我面临的问题是,我无法使用 std::sort(ops.begin(), ops.end(), std::mem_fun_ref(&parser::op_comp))
(其中OPS是一个 vector of op_info)
方法。我得到了以下错误,这听起来很符合逻辑。
错误:在静态成员函数中无效使用成员`parser::operators'。
我的问题是:我怎样才能强迫 std::sort 使用一个编译函数,使用类中非静态成员的元素?很明显,这个函数应该是非静态的,但是如果我不把它变成静态的,我就无法使用它。
使用一个漏斗而不是函数。
struct op_comp : std::binary_function<op_info, op_info, bool>
{
op_comp(parser * p) : _parser(p) {}
bool operator() (const op_info& o1, const op_info& o2) {
return _parser->op_comp(o1, o2);
}
parser * _parser;
};
这样方法 op_comp
可以保持非静态。然而,调用者需要一个解析器的实例,所有的操作符都存储在那里。这就是我们的新漏斗的用法。
std::sort(ops.begin(), ops.end(), op_comp(&my_parser));
Where my_parser
是你正在使用的解析器实例。或者,如果你正在调用 std::sort
的解析器中,你可以简单地写。
std::sort(ops.begin(), ops.end(), op_comp(this));
把运算符也做成静态的, 然后你就可以在op_comp中使用它了。
另外,也可以用一个漏斗来代替函数。
class myCompareClass {
public:
bool operator() (
const op_info& o1, const op_info& o2) {
op_def& op1 = operators[o1.op_char];
op_def& op2 = operators[o2.op_char];
return op1.priority > op2.priority;
}
private:
... operators ...
} myCompareObject;
std::sort(ops.begin(), ops.end(), myCompareObject)
查看更多例子 cplusplus.com
如果你想让 op_comp 成为非静态的,你可以使用 Boost.Lambda 或 Boost.Bind。
parser my_parser;
sort(ops.begin(), ops.end(), bind(&parser::op_comp, ref(my_parser)));