tags:

views:

495

answers:

3

I'd like to obtain the pointer to the object and an indication of which method the functor will call from a functor constructed using boost::function and boost::bind. This will allow me to automatically determine the order in a which bunch of functors must be executed.

The following (pseudo) code (see POINTER_OF & METHOD_OF) shows what I'm trying to do:

class myClassA
{
  public:
    DoIt(int i) { return i+i; }
};

class myClassB
{
  public:
    DoItToo(double d) { return d*d; }
};

typedef boost::function0<int> Functor;

myClassA classA;
myClassB classB;

Functor funcA = boost::bind( &myClassA::DoIt, &classA, 10 );
Functor funcB = boost::bind( &myClassB::DoItToo, &classB, 12.34 );

// Create a vector containing some functors and try to determine the objects
// they are called upon and the methods they invoke
std::vector<Functor> vec;
vec.push_back( funcA );
vec.push_back( funcB );

for (int i = 0; i < vec.size();i++)
{
  if (POINTER_OF(vec[i]) == &classA)
  {
    // This functor acts on classA
    if (METHOD_OF(vec[i]) == &myClassA::DoIt)
    {
      // This functor calls the 'DoIt' method.
    }
    else if (METHOD_OF(vec[i]) == &myClassB::DoItToo)
    {
      // This functor calls the 'DoItToo' method.
    }
  }
  // etc...
}

Thanks in advance!

+4  A: 

I know that the following is not a strict answer to your question but.

Don't do this. Use polymorphism instead. It is one of the strangest things I saw in my current project code: if function pointer points to "someFunction" - do some extra acctions.

You can add extra behavior without changing your classes much with Decorator design pattern. That will extend your myClassA::DoIt with Decorator::DoIt.

http://en.wikipedia.org/wiki/Decorator_pattern

Mykola Golubyev
Maybe my example isn't clear ;-) I only need to determine the object and method called on it for a large list of functors to determine the execution order of the methods as they all have side-effects and depend on eachother (used in machine control - objects represent physical systems)
@lasser - that doesn't change the good sense of Mykola's answer. You need a list of objects which have a priority and a function.
Daniel Earwicker
A: 

No, I don't think you can get the target of a boost function that is set to a boost bind (ie METHOD_OF). According to this post on the boost mailing list this is because the return type of bind is not formally specified.

Edit: Link to an earlier question that is some-what related to this question: demote-boostfunction-to-a-plain-function-pointer

Mic
A: 

boost::function objects are equality comparable, so you should be able to do stuff like

if (vec[i] == boost::bind( &myClassA::DoIt, &classA, 10 ))
{
   // ... this Functor calls DoIt on classA with argument 10
}

I suspect you're looking for something more general though. Digging into the implementation details of boost/function_equal.hpp (ie boost::bind's function_equal_impl) might give you some idea how to selectively test a subset of the boost::bind arguments.

But I really think youd be better off with a polymorphism-based solution, or just aggregating the function objects with some metadata.

timday
Thanks for your comment, timday. If I understand right, when I use equal_impl I will still face the problem of getting the object and method out of boost::bind... Comparing boost::bind instances also won't work as they are different when different parameters are passed.
The equality test implementation itself must have access to the object and method (to compare them), which is why I suggest looking at how those are implemented.
timday