views:

269

answers:

3

Hello everyone,

I'm currently developing a syntaxic analyser class that needs, at a point of the code, to sort structs holding info about operators. Each operator has a priority, which is user-defined through public member functions of my analyser class. Thus, when sorting, I need my sorting function to order elements based on the priority of the corresponding operator. I'm using the following code to compare elements:

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;
}

Note that I had to make this function static, since it's defined inside of a class.

In fact, my compare function compares elements of type op_char, and I retrieve the operator def from a map which contain elements of type op_def, which have a field "priority".

The problem I'm facing is that I can't manage to use std::sort(ops.begin(), ops.end(), std::mem_fun_ref(&parser::op_comp)) (where ops is a vector of op_info) method. I get the following error, which sounds quite logical :

error: invalid use of member `parser::operators' in static member function

Here is my question : how can I force std::sort to use a comp function that makes use of elements from non-static members of the class ? Obviously the function should be non-static, but I can't manage to use it if I don't make it static...

Thanks in advance for your help, CFP.

+4  A: 

Make operators static as well, and you'll be able to use it in op_comp.

Alternatively, use a functor instead of a function:

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)

See more examples at cplusplus.com

Bill
Thank you! Yet my problem is that the content of `operators` is dependent on which instance of `parser` I'm dealing with.Another solution, I realized, was also to simply copy the "priority" information to each op_info object when creating such an object.I'm very impressed by how fast and good answers are, and by how nice the people are, on this website. Thank you!
CFP
+2  A: 

Use a functor instead of a function:

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;
};

This way the method op_comp can stay non-static. However the caller needs an instance of the parser, where are all the operators are stored. This is the usage of our new functor:

std::sort(ops.begin(), ops.end(), op_comp(&my_parser));

Where my_parser is the instance of parser you are using. Alternatively, if you are calling std::sort from the parser, you can simply write:

std::sort(ops.begin(), ops.end(), op_comp(this));
Miroslav Bajtoš
Great ! This indeed works very well.
CFP
+3  A: 

If you want op_comp to be non-static you can use Boost.Lambda or Boost.Bind:

parser my_parser;
sort(ops.begin(), ops.end(), bind(&parser::op_comp, ref(my_parser)));
TimW
+1. Use TR1 `std::tr1::bind` if available; otherwise `boost::bind`.
Pavel Minaev