下面将介绍泛型编程的最重要的组件,他们是: 1。编译期断言 2。编译期转换检测 3。编译期选择 4。编译期多态 5。代码容器
再一次说,这是泛型里最重要的组件,值得你去理解和使用,他们的实现有很多版本,Boost和Loki都有实现,在认真比较以后,我认为Loki确实更加简单和强大,所以我选择Loki的代码进行示例,如果你有兴趣深入了解,请读《C++设计新思维》。
值得注意的是,为了便于理解,我把Loki的代码进行了适当修改。
1。编译期断言
实现: template<int> struct CompileTimeError; template<> struct CompileTimeError<true> {};
#define STATIC_CHECK(expr, msg) \ { CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
原理: 利用template<> struct CompileTimeError<false>并没有特化体,所以产生他的实例ERROR_##msg编译器就会报错。
使用: const int i = 0; STATIC_CHECK(i==0, "i因该等于0");
2。编译期转换检测
实现: template <class T, class U> struct ConversionHelper { typedef char Small; struct Big { char dummy[2]; }; static Big Test(...); static Small Test(U); static T MakeT(); };
template <class T, class U> struct Conversion { typedef ConversionHelper<T, U> H; enum { exists = sizeof(typename H::Small) == sizeof(H::Test(H::MakeT())) }; enum { exists2Way = exists && Conversion<U, T>::exists }; enum { sameType = false }; }; template <class T> struct Conversion<T, T> { enum { exists = 1, exists2Way = 1,sameType = 1 }; }; template <class T> struct Conversion<void, T> { enum { exists = 1, exists2Way = 0,sameType = 0 }; }; template <class T> struct Conversion<T, void> { enum { exists = 1, exists2Way = 0,sameType = 0 }; }; template <> class Conversion<void, void> { public: enum { exists = 1, exists2Way = 1,sameType = 1 }; };
#define SUPERSUBCLASS(T, U) \ (Conversion<const U*, const T*>::exists && \ !Conversion<const T*, const void*>::sameType)
#define SUPERSUBCLASS_STRICT(T, U) \ (SUPERSUBCLASS(T, U) && \ !Conversion<const T, const U>::sameType)
原理: 利用函数的参数列表的型别推测机制得到编译器使用哪个函数,而函数返回型别,接着利用 sizeof()一定会在编译期求出值来获得返回型别的大小,依此来判断调用了哪个函数,然后在利用enum是编译期确定的常数,把sizeof()返回的值具体化出来。
使用: class A { }; class B : public A { };
STATIC_CHECK( SUPERSUBCLASS(A, B), "A因该是B的基类");
3。编译期选择
实现: template <bool flag, typename T, typename U> struct Select { typedef T Result; }; template <typename T, typename U> struct Select<false, T, U> { typedef U Result; };
原理: 模板偏特化
使用: class A { }; class B { };
template<bool b> class C : public Select<b, A, B> { };
4。编译期多态
实现: template<class T> class Relex { private: Relex(const Relex&); Relex& operator = (const Relex&); public: typedef T _HostType; typedef T& _HostReference; typedef T* _HostPointer; public: Relex() { } T* GetHostPtr() { return reinterpret_cast<T*>(this); } };
原理: 模板的迭代编译
使用: template<class T> struct A : Relex<T> { void func1() { GetHostPtr()->func2(); } };
template<class T> struct B : Relex<T> { void func2() { GetHostPtr()->func1(); } };
template<template<class>class T1, template<class>class T2> class C_Impl : public T1<C_Impl>, public public T2<C_Impl> { };
typedef C_Impl<A, B> C;
5。代码容器 这里的实现非常巨大,就不写了,你可以自己去看代码
实现: template <class T, class U> struct Typelist //请想想STL里的list,非常象。这里的Tail又是一个Typelist,这样形成一个链 { typedef T Head; typedef U Tail; }; //Typelist的头是Typelist<T, NullType>,我们把NullType作为链的尾。
struct NullType { }; struct EmptyType { };
//下面是操作Typelist的类
template <class TList> struct Length; template <class TList, unsigned int index> struct TypeAt; template <class TList, unsigned int index,typename DefaultType = NullType> struct TypeAtNonStrict; template <class TList, class T> struct IndexOf; template <class TList, class T> struct Append; template <class TList, class T> struct Erase; template <class TList, class T> struct EraseAll; template <class TList> struct NoDuplicates; template <class TList, class T, class U> struct Replace; template <class TList, class T, class U> struct ReplaceAll; template <class TList> struct Reverse; template <class TList, class T> struct MostDerived; template <class TList> struct DerivedToFront;
//下面就是代码容器,典型的模板递归和模板偏特化的运用,请仔细看,其实很简单
template <class TList, template <class> class Unit> class GenScatterHierarchy; template <class T1, class T2, template <class> class Unit> class GenScatterHierarchy<Typelist<T1, T2>, Unit> : public GenScatterHierarchy<T1, Unit> , public GenScatterHierarchy<T2, Unit> { public: typedef Typelist<T1, T2> TList; typedef GenScatterHierarchy<T1, Unit> LeftBase; typedef GenScatterHierarchy<T2, Unit> RightBase; template <typename T> struct Rebind { typedef Unit<T> Result; }; }; template <class AtomicType, template <class> class Unit> class GenScatterHierarchy : public Unit<AtomicType> { typedef Unit<AtomicType> LeftBase; template <typename T> struct Rebind { typedef Unit<T> Result; }; }; template <template <class> class Unit> class GenScatterHierarchy<NullType, Unit> { template <typename T> struct Rebind { typedef Unit<T> Result; }; };
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 <int i, class H> typename FieldHelper<H, i>::ResultType& Field(H& obj);
原理: metaprogram,也就是模板递归,模板偏特化。
使用: 使用Loki里提供的宏,Loki提供了50个宏
运用1,实现Tuple:
template <class T> struct TupleUnit { T value_; operator T&() { return value_; } operator const T&() const { return value_; } };
template <class TList> struct Tuple : public GenScatterHierarchy<TList, TupleUnit> { };
class A { }; class B { }; class C { }; class D { };
typedef Tuple<TYPELIST_4(A, B, C, D)> TupleClass;
TupleClass obj;
B& b = Field<1>(obj);
运用2,实现一个抽象工厂:
namespace Noir_Impl { template<class P> struct CAF_Product { P* Create_Impl() { return new P; } };
template<class CProductList> class CAF_AbstractFactory : public Loki::GenScatterHierarchy< CProductList, CAF_Product > { }; };
template<class IProductList, class CProductList> struct Simple_AbstractFactory : public IProductList, private Noir_Impl::CAF_AbstractFactory< CProductList > { template<class IP> IP* Create() { typedef TypeAt< CProductList, IndexOf< IProductList, IP >::value > CP; return CP::Create_Impl(); } };
class IA { }; class IB { }; class IC { }; class ID { };
class A : public IA { }; class B : public IB { }; class C : public IC { }; class D : public ID { };
typedef Simple_AbstractFactory< TYPELIST_4(IA, IB, IC, ID), TYPELIST_4(A, B, C, D) > MyAF;
MyAf factory;
IA* pA = factory.Create<A>(); IB* pB = factory.Create<B>(); IC* pC = factory.Create<C>(); ID* pD = factory.Create<D>();
|