产生了typelist之后, 该轮到typelist的一些应用了, 那就是用typelist自动产生class。 typelist就是产生class的基础。
GenScatterHierarchy : 产生散乱的继承体系, 最后其实是一个多重继承。 定义:
template <class TList, template <class> class Unit>
class GenScatterHierarchy;
生成的继承体系的基类最终就是几个Unit<Tp>类, Tp是TList中的类型. 实现:
template <class T1, class T2, template <class> class Unit>
class GenScatterHierarchy<Typelist<T1, T2>, Unit>
: public GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit>
, public GenScatterHierarchy<T2, Unit>
{ };
template <class AtomicType, template <class> class Unit>
class GenScatterHierarchy : public Unit<AtomicType>
{ };
template <template <class> class Unit>
class GenScatterHierarchy<NullType, Unit>
{ };
应用方法:
template <class T>
struct Holder { T Value_;}
typedef GenScatterHierarchy<TYPELIST_3(int, string, Widget), Holder> WidgetInfo;
这样就生成了一个递归结构, WidgetInfo处于最低层, 可以通过动态的类型转换将WidgetInfo& 类型转换为任何一个基类, 然后使用基类相应的Value_值。
为了更方便的使用这个生成的继承层次, 定义了Field这个函数, Field根据对象可以得到递归层次中的某个基类的引用。
template <class T, class TList, template<class> class Unit>
Unit<T>& Field(GenScatterHierarchy<TList, Unit>& obj)
{ return obj;}
但是当typelist中有几个相同的类型是, 会出现歧义, 找不到合适的转换路径。所以还需要一个Field, 通过索引来找到合适的基类。其中用到了FieldHelper.
template<class TList, template<class> class Unit>
Unit<TList::Head>& FieldHelper(GenScatterHierarchy<TList, Unit>& obj, Int2Type<0>)
{ GenScatterHierarchy<TList::Head, Unit>& leftBase = obj;
return leftBase;}
template<int i, class TList, template<class> class Unit>
Unit<TypeAt<TList, index>::Result>& FieldHelper(GenScatterHierarchy<TList, Unit>& obj, Int2Type<i>)
{ GenScatterHierarchy<TList::Tail, Unit>& rightBase = obj;
return FieldHelper(rightBase, Int2Type<i-1>());}
template <int i, class TList, template<class> class Unit>
Unit<TypeAt<TList, index>::Result>& Field(GenScatterHierarchy<TList, Unit>& obj)
{ return FieldHelper(obj, Int2Type<i>();}
上述实现中的index, 我怀疑应该是i, 因为返回值是不能进行模板推断的。 而且将index换成i却可以得到合理的解释(我个人的推断而已)
因为GenScatterHierarchy是多重继承,所以需要耗费大量的虚指针, 故而又有一个新的线性继承体系GenLinearHierarchy.
template
<
class TList,
template <class AtomicType, class Base> class Unit,
class Root = EmptyType
>
class GenLinearHierarchy;
template
<
class T1,
class T2,
template <class, class> class Unit,
class Root
>
class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root>
: public Unit< T1, GenLinearHierarchy<T2, Unit, Root> >
{
};
template
<
class T,
template <class, class> class Unit,
class Root
>
class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root>
: public Unit<T, Root>
{
};
template
<
template <class, class> class Unit,
class Root
>
class GenLinearHierarchy<NullType , Unit, Root>
: public Root // is this better: Unit<NullType, Root> ?
{
};