3
class Foo 
{
    double f1( int x, std::string s1 );
    double f2( int x, SomeClass s2 );
}

I want to be able to bind Foo.f1's s1 without an instance of foo to create in essense

typedef double (Foo::* MyFooFunc)( int ) 

MyFooFunc func1 = boost::bind( &Foo::f1, _1, _2, "some string" );
MyFooFunc func2 = boost::bind( &Foo::f2, _1, _2, SomeClass );

Then I pass func1 and func2 as parameters to other functions, inside which Foo is finally bound:

void SomeOtherFunction( MyFooFunc func )
{
     Foo foo;
     boost::function< double (int) > finalFunc =
          boost::bind( func, foo, _1 );
}

Questions: Is this possible? If yes, 1) how to achieve it? 2) What's the declaration of MyFooFunc?

BЈовић
  • 62,405
  • 41
  • 173
  • 273
Candy Chiu
  • 6,579
  • 9
  • 48
  • 69
  • It depends on `SomeOtherFunction` is declared. Note that your second typedef is *not* a function pointer, it's pointer-to-member-function (PTMF), which is an entirely different and incompatible concept. Wrapping everything in `std::function` or `std::tr1::function` or `boost::function` would probably be the most powerful solution. – Kerrek SB Aug 05 '11 at 14:31
  • There are actually two issues here: 1) binding PTMF without an instance. 2) express the result of the bind as boost function. For 1), I tried boost::bind( &Foo::f1, _1, _2, "hello" ). That didn't work. For 2), I suspect it's boost::function< int (boost::shared_ptr,int) >. – Candy Chiu Aug 05 '11 at 14:53

2 Answers2

4
typedef double (Foo::* MyFooFunc)( int );

MyFooFunc func1 = boost::bind( &Foo::f1, _1, _2, "some string" );

The result of boost::bind is not a pointer to member, so func1 cannot be initialized as such on the second line. The result of boost::bind is an unspecified type (which will depend on the parameters). If you're using C++0x, the simplest way to name the result of a call to bind is to use auto:

auto func1 = boost::bind( &Foo::f1, _1, _2, "some string" );

Another simple way (not restricted to C++03) is simply to not name the result, but to use it on the spot:

SomeOtherFunction(boost::bind(&Foo::f1, _1, _2, "some string"));

Or, you can use type-erasure to store the result of boost::bind into a boost::function, which you seem to be familiar with. boost::function<double(Foo&, int)> is a possibility but not the only choice.


We now need to find the appropriate signature for SomeOtherFunction: again, a pointer to member can't be initialized from the result of a call to boost::bind, so void SomeOtherFunction(MyFooFunc func); won't work. You can make the function a template instead:

template<typename Func>
void SomeOtherFunction( Func func )
{
     Foo foo;
     boost::function< double (int) > finalFunc =
          boost::bind( func, foo, _1 );
}

If a template is not preferrable, then you must use some kind of type-erasure such as, again, boost::function.

void SomeOtherFunction(boost::function<double(Foo&, int)> const& func);

(once again other boost::function types are possible depending on details such as passing a ref-to-const as opposed to a ref-to-non-const)

Luc Danton
  • 34,649
  • 6
  • 70
  • 114
0

Try this:

boost::bind(&Foo::f1, object, _1, _2);

object is an instance of class Foo. _1 and _2 are the argument placeholders.

Jens Luedicke
  • 964
  • 2
  • 8
  • 20
  • There's probably just one placeholder, since the OP wants `Foo::f1(int)` I think... – Kerrek SB Aug 05 '11 at 14:33
  • Note that if `object` is a value and not a pointer, you should do `boost::ref(object)` or `&object`, otherwise binder will operate on a copy. – Cat Plus Plus Aug 05 '11 at 14:39
  • Sorry for the confusion. I want to separate the binding of an instance of Foo (object) and the non uniform parameters (s1,s2) into 2 steps. – Candy Chiu Aug 05 '11 at 14:49