Suppose I have a function which takes a nullary functor as an argument:
void enqueue( boost::function<void()> & functor );
I have another function which takes an int and does something internally:
void foo( int a);
I would like to nest, but not compose, these together so that I get a functor with the signature:
boost::function<void(int)> functor
Which when called with a value – say 4 – performs the following:
enqueue( boost::bind(&foo, 4) )
My first attempt was the following:
boost::function<void(int)> functor = boost::bind(&enqueue, boost::bind(&foo,_1))
This fails because bind performs composition when given a nested bind. foo was first called, then the value void was “returned” to enqueue, which fails.
My second attempt was the following:
boost::function<void(int)> functor = boost::bind(&enqueue, boost::protect( boost::bind(&foo, _1) ) )
This failed because enqueue accepts a nullary, not unary functor.
Can what I’m seeking be done?
Other information:
- This is basically identical to the unanswered boost forum question from 6 years ago:
http://lists.boost.org/boost-users/2004/07/7125.php - Some reading suggests that using boost::lambda::bind with boost::lambda::unlambda and boost::lambda::protect may do what I’m seeking. Unfortunately boost::lambda has an unacceptably low number of allowed placeholders (3), and high compile-time overhead.
Interesting question…
What you basically want is a “bound call to bind”. In the same manner than binding a call to
foo(x, y)is writtenbind(&foo, x, y), binding a call tobind(&foo, x)should be likebind(&bind, &foo, x). However, taking the address of an overloaded function quickly gets ugly and, asboost::bindhas more overloads than I could count, it gets pretty ugly:You’ll probably agree that, while “interesting”, the above won’t win readability contests. Separating the obtention of the proper bind overload from the rest makes things a bit more manageable:
but I still hesitate to recommend it 😉
Edit:
Answering the OP’s comment about how/if C++0x would help to clean the syntax: It does: