
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