Boost logo

Boost Users :

From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2008-02-22 14:22:54


AMDG

Scott Meyers wrote:
> I have a set of types representing features code might have, e.g.,
>
> typedef mpl::vector<ExceptionSafe, ThreadSafe, ReallyFast, GPLed> Features;
>
> These can occur in any combination as sets of features, e.g.,
>
> tyepdef FeatureSet<ExceptionSafe> F1;
> typedef FeatureSet<ThreadSafe, ExceptionSafe> F2;
> typedef FeatureSet<ReallyFast, ExceptionSafe, GPLed> F3;
> <snip>
>
> I'm looking for a way to automatically generate an inheritance hierarchy that
> will give me the behavior I've described. For the above example, the hierarchy
> has four levels. The root is all the features, because any subset of features
> is permitted to be implicitly convertible to the set of all features.
>
> Root: FeatureSet<ExceptionSafe, ThreadSafe, ReallyFast, GPLed>
>
> The leaves are the individual features:
>
> Leaves: FeatureSet<ExceptionSafe>
> FeatureSet<ThreadSafe>
> FeatureSet<ReallyFast>
> FeatureSet<GPLed>
> <snip>
>
> Is there some way for me to use the MPL to automatically generate the hierarchy
> I need?
>
> Thanks,
>
> Scott
>

There's nothing that works out of the box. Here's a quick hack:

#include <boost/mpl/begin.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/empty_base.hpp>
#include <boost/mpl/erase.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/not_equal_to.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>

namespace mpl = boost::mpl;

template<class T1, class T2=void>
struct virtual_inherit : virtual T1, virtual T2 {};
template<class T1>
struct virtual_inherit<T1, void> : virtual T1 {};

template<class S>
struct make_features;

template<class S, class Iter = typename mpl::begin<S>::type>
struct make_features_base {
    typedef typename make_features<typename mpl::erase<S,
Iter>::type>::type item;
    typedef typename make_features_base<S, typename
mpl::next<Iter>::type>::type next;
    typedef virtual_inherit<next, item> type;
};

template<class S>
struct make_features_base<S, typename mpl::end<S>::type> {
    typedef virtual_inherit<mpl::empty_base> type;
};

template<class S>
struct features :
    virtual mpl::eval_if<mpl::not_equal_to<mpl::size<S>, mpl::int_<1> >,
        make_features_base<S>,
        mpl::identity<virtual_inherit<mpl::empty_base> >
>::type {};

template<class S>
struct make_features {
    typedef features<typename mpl::copy<S,
mpl::back_inserter<mpl::vector0<> > >::type> type;
};

int main() {
    typedef make_features<mpl::vector<int, char, double> >::type f1;
    typedef make_features<mpl::vector<int, double> >::type f2;
    typedef make_features<mpl::vector<char> >::type f3;
    BOOST_MPL_ASSERT((boost::is_base_and_derived<f2, f1>));
    BOOST_MPL_ASSERT((boost::is_base_and_derived<f3, f1>));
}

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