Is it possible to use boost::bind to effectively concatenate functions?
Assume that I have a boost::function of with an arbitrary signature called type CallbackType
.
- Is it possible to use
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::bi开发者_开发知识库nd(doIt) );
object.doBoth();
return 0;
}
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).
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.
精彩评论