views:

174

answers:

3

I am using Boost Spirit parser, and as the parser is parsing, semantic actions are reflected to an instance of the class ParserActions.

Here is the code for the parser (the relevant part)

struct urdf_grammar : public grammar<urdf_grammar> {

template <typename ScannerT>
        struct definition {

    definition(urdf_grammar const& self) {


        prog = (alpha_p >> *alnum_p)[&(self.actions.do_prog)];

    }

    rule<ScannerT> prog;

    rule<ScannerT> const&
            start() const {
        return prog;
    }
};

const ParserActions & actions;

explicit urdf_grammar(const ParserActions & actions = ParserActions()) : actions(actions) {
}  
};
+3  A: 

To take the address of a member variable or function, use:

&MyClass::MyMember

To call a member function pointer, use one of:

(my_class.*ptr_to_member)( /* arguments */ )
(my_ptr->*ptr_to_member)( /* arguments */ )

Random link I found on Google with more info: http://www.goingware.com/tips/member-pointers.html

AshleysBrain
+1  A: 

There is a fundamental difference between function pointers and member function pointers:

  • a function pointer must be called with arguments of the correct types,

  • a member function pointer must be called with an object of the correct type and arguments of the correct types.

Building a member function pointer like you do from an object does not register the object in the pointer.

If you want such a thing, there are various libraries doing so (you have a boost tag, see bind and signals for examples of such).

AProgrammer
+3  A: 

In order to call a member function of an object you need to provide two things:

  1. the address of the member function, as said before you can get that by writing &my_class::my_member
  2. the pointer (or a reference) to the instance of the object you want the member function be invoked for

Spirit semantic actions expect you to provide a function or function object exposing a certain interface. In your case the expected interface is:

void func(Iterator first, Iterator Last);

where Iterator is the iterator type used to call the parse function (accessible through typename ScannerT::iterator_t). What you need to do is to create a function object exposing the mentioned interface while still calling your member function. While this can be done manually, doing so is tedious at best. The simplest way to create a function object is by using Boost.Bind:

prog = (alpha_p >> *alnum_p)
       [
           boost::bind(&ParserActions::do_prog, self.action)
       ];

which will create the required function object for you, binding and wrapping your member function.

All this assumes your member function does not take any arguments. If you need to pass the pair of iterators the semantic action will be invoked with to your function the construct needs to be written as:

prog = (alpha_p >> *alnum_p)
       [
           boost::bind(&ParserActions::do_prog, self.action, _1, _2)
       ];

instructing the function object to forward its first and second parameter to the bound function.

hkaiser
myahya
Yes, you're right. I wrote the above from the top of my head...
hkaiser
I fixed the code in my answer above to reflect the correct syntax.
hkaiser