
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