Boost logo

Boost Users :

From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2008-02-26 00:00:19


AMDG

Scott Meyers wrote:
> Steven Watanabe wrote:
>
>> 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>));
>>
>
> Sorry for taking so long to reply, but TMP always makes my head explode, and it
> takes a while to pick up the pieces and put them back together. In this case, I
> could have saved myself the explosion, because this interface offers behavior
> that is backwards from what I want. The conversion I want to allow is from
> fewer features to more, so I don't want f2 and f3 to be bases of f1, I want f1
> to be a base for both f2 and f3.
>

Oops. I see.

>
> What I don't know is a good way to give Features<T> the appropriate number of
> virtual base classes. Can somebody help?
>

The key thing to note is that you don't need to directly inherit
from N base classes. You can create a two argument template
and chain them together.

#include <boost/mpl/empty_base.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/remove_if.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/copy_if.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>

template<class Base1, class Base2>
struct VirtualInherit : virtual Base1, virtual Base2 {
};
template<class Sequence>
struct MakeFeatures;

using namespace boost::mpl;

typedef vector<int, char, double, void> AllFeatures;

template<class T, class U>
struct Difference : remove_if<T, contains<U, _> > {};

template<class Original, class New>
struct Insert : copy_if<AllFeatures, contains<typename
push_back<Original, New>::type, _1> > {};

template<class Original, class Added>
struct GetFeaturesBases : transform<Added, MakeFeatures<Insert<Original,
_1> > > {};

template<class FeatureList>
struct Features : virtual fold<
    typename GetFeaturesBases<FeatureList, typename
Difference<AllFeatures, FeatureList>::type>::type,
    empty_base,
    VirtualInherit<_, _>
>::type {};

template<class Sequence>
struct MakeFeatures {
    typedef Features<typename copy<Sequence, back_inserter<vector0<> >
>::type> type;
};

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

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