Boost logo

Boost :

From: Christian Holmquist (c.holmquist_at_[hidden])
Date: 2006-12-19 08:52:20

First of all a great thank-you (!!!) to Joel and the rest behind the
development of fusion.
It's solved so many tasks for me and made me write so little code the past
months I probably shouldn't even get paid.
database-abstraction, remote function invocation with async handlers,
console/web interface invocation, etc.. It's changed my perception of
effective programming to a complete new level.
What before was a struggle with mpl, is now clean and easy.

Ok, so to my humble problem. I'm constantly finding myself writing those
overloaded functions like:

template<class A0, class A1, ....>
void operator()(const A0& a0, const A1& a1, ...) const
 do_something_very_clever(fusion_sequence_type(a0, a1, ...));

This is cumbersome and boring, and usually I just add the overloads when
someone else needs it.. It's not always the case I can know beforehand to
overload const T& or just T& also, but it depends on the use case.

Anyways, my idea is to generate the correct overloaded operator()(...) by
specializing on the size of the fusion sequence, instantiate the sequence
with the parameters when invoked by client code, and then use CRTP downcast
to invoke a function with the fusion sequence. This way I can do the job
with my neat fusion sequence without client-code needing to mess with
boost::fusion::tie and boost::ref etc, and I don't have to bother with the
I guess an example would explain better than the above noise.
Here's what a trivial multi-dispatch function would look like. I use
function_types here to build my fusion sequence, but it could just as well
have been some preprocessor enumeration dito instead.
The overloading class selecting the overload is named to pack_args

template<class Func>
struct simple_signal : public pack_args
simple_signal const,
    typedef boost::function1<void, const sequence_type> function;

    template<class F>
    struct invoke
        invoke(const F& f) : f_(f) {}
        void operator()(const sequence_type& seq) const
            boost::fusion::unpack_args(f_, seq);
        F f_;

    template<class F>
    void connect(const F& f)

    // callback from pack_args. I agree this convention looks ugly, but
it'll do for now..
    void on_packed_args(const sequence_type& seq) const
        for(std::list<function>::const_iterator i = m_functions.begin(); i
!= m_functions.end(); ++i)
    std::list<function> m_functions;

I can now use the above with
simple_signal<void(int const, int const) > sig;
sig(24, 54); // call all connected functions here..

If I have overlooked anything in fusion that would give me this
functionality, please point me in the right direction and I'll be forever
grateful :)


Boost list run by bdawes at, gregod at, cpdaniel at, john at