Boost logo

Boost Users :

From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2008-03-26 12:33:06


AMDG

Robert Dailey wrote:
> Would you mind going over what exactly this is doing? I'm having a
> hard time wrapping my head around it. The documentation isn't helping
> much either, as I've never used these before and the descriptions are
> very confusing.
>
> I also didn't see a version of mpl::transform that only took 1
> template argument. Is this correct?

You're right. I was in too much of a hurry before.
Here's something that actually compiles.

#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/inherit_linearly.hpp>
#include <boost/mpl/inherit.hpp>
#include <boost/signal.hpp>
#include <boost/variant.hpp>

namespace mpl = boost::mpl;

// bring _ into scope.
using namespace mpl::placeholders;

struct WalkPacket {};
struct ChatPacket {};
struct QuestPacket {};

// a metafunction to create a signal type that
// takes T as is argument by const reference.
template<class T>
struct make_signal {
    typedef boost::signal<void(T const&)> type;
};

// a type list of all the possible packet types.
typedef mpl::vector<WalkPacket, ChatPacket, QuestPacket> packet_types;
// take the list of packet types and transform it
// to get the signal types. The result will be
// equivalent to
// mpl::vector<signal<void(WalkPacket const&)>, signal<void(ChatPacket
const&)>, signal<void(QuestPacket const&)> >
//
// make_signal<_> is an mpl lambda expression. _
// is a placeholder which in this context means
// to substitute the first argument to the
// metafunction. In other words mpl::apply<make_signal<_>, T>
// will replace _ with T and then return the nested ::type
// typename make_signal<T>::type.
typedef mpl::transform<packet_types, make_signal<_> >::type signals;
// A type that inherits from all of the signal types.
//
// The mpl::inherit<_, _> is similar to make_signal<_> above,
// except that the first _ refers to the first argument and
// and the second _ refers to the second argument.
// mpl::inherit_linearly starts with an initial base class
// which defaults to mpl::empty_base, takes the
// first type in signals, and applies mpl::inherit to
// the two bases. inherit<empty_base, WalkPacket>.
// Then, it continues with the second element of signals
// to get inherit<inherit<empty_base, WalkPacket>, ChatPacket>
// And so on.
// inherit just inherits from both it's arguments.
//
// This could really be replaced by a fusion::set.
typedef mpl::inherit_linearly<signals, mpl::inherit<_, _> >::type
signal_holder;

struct signal_visitor : boost::static_visitor<> {
    explicit signal_visitor(signal_holder& holder) : holder_(holder) {}
    signal_holder& holder_;
    template<class T>
    void operator()(T const& t) const {
        // up-cast to correct type of signal.
        return(static_cast<typename make_signal<T>::type&>(holder_)(t));
    }
};

typedef boost::make_variant_over<packet_types>::type packet;

int main() {
    packet p = WalkPacket();
    signal_holder signals;
    boost::apply_visitor(signal_visitor(signals), p);
}

In Christ,
Steven Watanabe


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net