how to combine 2 independent boost::bind() into one boost::function?

1.7k views Asked by At

I have 2 functions f() and g(). I want to call them in order every time. Can I get a boost::function to do this? E.g. something like:

boost::function functor = boost::bind( boost::bind(f), boost::bind(g) );

Extend this further, say it takes arguments, then what I need is a chain of responsibility. Each node does something with arguments, then followed by next node of chain. How do I do that?


Update Thanks for Seth Carnegie's comments. I think what I really want is how to construct a chain of responsibility into a single boost::function, each node of chain can be constructed by using boost::bind().

3

There are 3 answers

1
Carsten Greiner On

Have you considered using boost::signal ?

With boost::signal you can connect multiple function calls into one.

#include <boost/signal.hpp> 
#include <iostream> 

void f() 
{ 
  std::cout << " Hello" << std::flush; 
} 

void g() 
{ 
  std::cout << " World" << std::endl; 
} 

int main() 
{ 
  boost::signal<void ()> s; 
  s.connect(f); 
  s.connect(g); 
  s(); 
} 
2
AudioBubble On

Why not something like this?

#include <functional>

template <typename FirstFunctor, typename SecondFunctor>
void chainFunctionImpl(FirstFunctor first, SecondFunctor second)
{
   first();
   second();
}

template <typename FirstFunctor, typename SecondFunctor>
std::function<void(void)> chainFunction(FirstFunctor first, SecondFunctor second)
{
   return std::bind(chainFunctionImpl<FirstFunctor,SecondFunctor>,first,second);
}

Use should be relatively simple, just binding the functions in sequence, then calling the result. Theoretically any length of functions could be chained up.

Note that is theoretically possible to do this with passing an argument down the chain as well, but that level of template foo is way beyond me. http://ideone.com/Xvp5U is where I gave up.

0
Sven On

There is a quite easy solution using boost::lambda with its comma operator. In my case I am using it for a modificator function which is defined as (B is an arbitrary class for e.g. and A is a class which should be altered but resides in B and should not go outside)

void B::modify( boost::function<void(A&)> func );

My intention is to pass only the modificator to the modify function which makes it more easy to gain control when it is modified (for e.g. for emitting signals).

Sometimes I want to apply 2 modifier:

void A::setInvalid();
void A::setX( int x );

Calling in 2 steps which is not the way (just as reference to show how we want to use the modify method):

instanceA->modify( 
    boost::bind( &A::setInvalid, _1 );
instanceA->modify( 
    boost::bind( &A::setX, _1, 4 );

Using boost::lambda this can be joined to a single function call and therefore only one function is created:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace boost::lambda;
instanceA->modify(
    ( bind(&A::setInvalid, boost::lambda::_1)
    , bind(&A::setX, boost::lambda::_1, 4) ) );

Related to your question this would look then:

using namespace boost::lambda;
boost::function<void()> func = ( bind(f), bind(g) )