开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜