Reputation: 19239
Assume that I have a boost::function of with an arbitrary signature called type CallbackType
.
boost::bind
to compose a function that takes the same arguments as the CallbackType but calls the two functors in succession?I'm open to any potential solution, but here's a...
...Hypothetical example using some magic
template:
Template<typename CallbackType>
class MyClass
{
public:
CallbackType doBoth;
MyClass( CallbackType callback )
{
doBoth = bind( magic<CallbackType>,
protect( bind(&MyClass::alert, this) ),
protect( callback ) );
}
void alert()
{
cout << "It has been called\n";
}
};
void doIt( int a, int b, int c)
{
cout << "Doing it!" << a << b << c << "\n";
}
int main()
{
typedef boost::function<void (int, int, int)> CallbackType;
MyClass<CallbackType> object( boost::bind(doIt) );
object.doBoth();
return 0;
}
Upvotes: 6
Views: 1389
Reputation: 163287
Boost already provides a way to create a sequence of bound functions. Use Lambda's comma operator.
using namespace boost::lambda;
MyClass mc;
CallbackType object = (bind(&MyClass::alert, mc), bind(doIt, _1, _2, _3));
object(1, 2, 3);
That will create a new functor, object
. When you invoke that functor with three arguments, it will in turn call mc.alert()
before passing those arguments to doIt
. The parentheses are important.
For my example above to work, you'd need alert
to be a const
function. If it needs to be non-const, then either pass a pointer to mc
, or wrap it with boost::ref(mc)
. And you'll need to use Boost.Lambda's bind
rather than Boost.Bind's; the latter isn't compatible with Lambda's function-combining operators (comma, in particular).
Upvotes: 8
Reputation: 137810
template< class Callback >
struct pre_caller {
Callback c;
pre_caller( Callback in_c ) : c( in_c ) {}
void alert() {} // or an instance of a functor
operator()
{ alert(); c(); }
template< class T1 >
operator( T1 a ) // not sure if/what qualification to add to a
{ alert(); c( a ); } // or whether to attempt to obtain from
// function_traits<Callback>?
template< class T1, class T2 >
operator( T1 a, T2 b )
{ alert(); c( a, b ); }
template< class T1, class T2, class T3 >
operator( T1 a, T2 b, T3 c )
{ alert(); c( a, b, c ); }
// ad nauseam... and I mean nausea, maybe read up on Boost Preprocessor.
};
Boost Bind uses a lot of preprocessor hacking for its variadic voodoo, and unfortunately I don't think it provides a pattern or tools for head-patching which is essentially what this is.
Upvotes: 1