c++ 泛型编程 之Factor (c++ 设计新思维)

一:前言

         现在要实作一个泛化仿函数,泛化仿函数是将“请求(函数)封装起来”,存储与对象之中,该对象是具有“value语义”的,因此它支持拷贝,赋值和作为函数参数来传值(pass by value)。通过该对象可间接的处理它封装的请求,类似于boost 中的function功能。本实现采用的是《Modern C++ Design》中的方案。更详尽的说,它具有以下特点:

1.      可封装任何处理请求,它可接受函数指针,成员函数指针,仿函数,甚至其它泛化仿函数。

2.      具备型别安全性,不会将错误的型别匹配到错误的函数上。

3.      是一种带有“value语义的对象”。

首先介绍下C++中的可调用体:

1.      C风格的函数(C like function):  void fun();

2.      C风格的函数指针(C like pointto function): void (*pFun)();

3.      函数引用(reference to function),其行为本质上和const pointer to function类似。

4.      仿函数(functor),类中自定义了operator () 的对象。

5.      Operator.*和operator->*的施行结果

6.      构造函数

在上述的任一项,你可以在其右侧添加一对圆括号(),并在里头放入一组合适的参数。

先来讨论这样一个问题,既然想把函数请求封装到对象中,函数的参数如何确定?这里使用typelist(这是一个型别集,换句话说它包含型别列表)。这里就可以把typelist作为HTFunctor的一个模板参数,它包含所要封装函数的参数型别信息。下面就先介绍下typelist实作

二:HTTypeList

  1. template <class T, class U>  
  2. struct HTTypeList  
  3. {  
  4.     typedef T Head;  
  5.     typedef U Tail;  
  6. };  

这是typelist的基本实作(只需两个类型),现在问题是如何把n个类型连成链表。看下面这个例子就明白了

  1. typedef HTTypeList<char, HTTypeList<intint> >  

(利用模板参数推导,而且是编译器自动产生,而不是运行期哦),这样两个以上的参数都解决了。

现在问题如何定义一个参数的typelist。方法是,第二个模板参数设为NullType(空类型),这样每个typelist都以NullType结尾,相当于C字符串的\0功能。看NullType的实作:

  1. class HTNullType {};  

接着就要生产typelist了(一个参数,两个参数,三个参数……)。这里用到宏,暂且定义4个typelist。

  1. #define TYPELIST_1(T1) UTIL::HTTypeList<T1, UTIL::HTNullType>  
  2. #define TYPELIST_2(T1, T2) UTIL::HTTypeList<T1, TYPELIST_1(T2) >  
  3. #define TYPELIST_3(T1, T2, T3) UTIL::HTTypeList<T1, TYPELIST_2(T2, T3) >  
  4. #define TYPELIST_4(T1, T2, T3, T4) UTIL::HTTypeList<T1, TYPELIST_3(T2, T3, T4) >  


另外要解决的问题是,函数参数该是值类型(内部内型)还是引用类型(对于对象)。选择合适的类型显然能提高程序速度,你肯定不想传递大对象参数时而要额外拷贝。接下来这个东西就要登场了——( HTTypeTraits

三:HTTypeTraits

可用于“编译期根据型别作判断”的泛型技术。大家也可参看boost中的type traits。

  1. // 判断T及U是否标示同一个类型  
  2. template <typename T, typename U>  
  3. struct HTIsSameType  
  4. {  
  5. private:  
  6.     template<typename>  
  7.     struct In   
  8.     { enum { value = false }; };  
  9.   
  10.     template<>  
  11.     struct In<T>  
  12.     { enum { value = true };  };  
  13.   
  14. public:  
  15.     enum { value = In<U>::value };  
  16. };  
  1. // 依flag选择两个类型中的一个,true为T,false为U  
  2. template <bool flag, typename T, typename U>  
  3. struct HTSelect  
  4. {  
  5. private:  
  6.     template<bool>  
  7.     struct In   
  8.     { typedef T Result; };  
  9.   
  10.     template<>  
  11.     struct In<false>  
  12.     { typedef U Result; };  
  13.   
  14. public:  
  15.     typedef typename In<flag>::Result Result;  
  16. };  
  1. // 编译期bool型  
  2. typedef char HTYes;  
  3. struct HTNo { char padding[8]; };  
  4.   
  5. // 型别映射为型别,用于模板函数的偏特化,C++标准模板函数不能偏特化  
  6. template <typename T>  
  7. struct HTType2Type { typedef T Type; };  
  8.   
  9. // 判断T是否为类  
  10. template <typename T>  
  11. struct HTIsClass  
  12. {  
  13.     // U为类的话,会具现化此重载函数,因为参数为函数指针,即指向成员的函数指针  
  14.     template <typename U> static HTYes IsClassTest(void(U::*)(void));  
  15.     // U为非类,会具现化此重载函数  
  16.     // C++标准:只有当其它所有的重载版本都不能匹配时,具有任意参数列表的重载版本才会被匹配  
  17.     template <typename U> static HTNo IsClassTest(...);  
  18.   
  19.     // 对于sizeof,表达式不会被真正求值,编译器只推导出表达式的返回结果的型别,因此只需函数的声明即可  
  20.     static const bool value = sizeof(IsClassTest<T>(0)) = sizeof(HTYes);  
  21. };  
  22.   
  23. // 判断T是否为引用类型  
  24. template <typename T>  
  25. struct HTIsReference  
  26. {  
  27.     template <typename U> static HTYes IsReference(HTType2Type<U&>);  
  28.     template <typename U> static HTNo IsReference(...);  
  29.   
  30.     static const bool value= sizeof(IsReference(HTType2Type<T>())) == sizeof(HTYes);  
  31. };  
  32.   
  33. template <typename T>  
  34. class HTTypeTraits  
  35. {  
  36.   
  37. public:  
  38.     enum {   
  39.         isVoid =   
  40.         HTIsSameType<T, void>::value          ||  
  41.         HTIsSameType<T, const void>::value    ||  
  42.         HTIsSameType<T, volatile void>::value ||  
  43.         HTIsSameType<T, const volatile void>::value  
  44.     };  
  45.   
  46.     enum { isReference = HTIsReference<T>::value };  
  47.   
  48. private:  
  49.     template<bool IsRef>  
  50.     struct AdjReference  
  51.     {  
  52.         template<typename U>  
  53.         struct In { typedef U const & Result; };  
  54.     };  
  55.   
  56.     template<>  
  57.     struct AdjReference<true>  
  58.     {  
  59.         template<typename U>  
  60.         struct In { typedef U Result; };  
  61.     };  
  62.   
  63.     typedef typename AdjReference<isReference || isVoid>::  
  64.         template In<T>::Result AdjType;  
  65.   
  66.     // 正确的选择函数参数的类型  
  67.     // 对于精巧型(有构造函数和析构函数额外调用)采用引用传参数,对于纯量型(数值型别,枚举型别,指针,指向成员的指针)采用直接传值  
  68.     typedef typename HTSelect<HTIsClass<T>::value, AdjType, T>::Result ParmType;  
  69. };  

四:HTFunctor

HTTypeList及HTTypeTraits提供我们强大的功能。这让我们实作HTFunctor更加的方便。下面直接看代码。

  1. // Functor对象明显是个小对象,这里采用小对象分配器  
  2. // 使用了Command模式及IMPL模式  
  3. template <typename R>  
  4. struct HTFunctorImplBase : public HTSmallObject<>  
  5. {  
  6.     typedef R   ResultType;  
  7.     typedef HTEmptyType Parm1;  
  8.     typedef HTEmptyType Parm2;  
  9. };  
  10.   
  11. template <typename R, class TList, class ObjClass>  
  12. struct HTFunctorImpl;  
  13.   
  14. // 无参数版本  
  15. template <typename R, class ObjClass>  
  16. struct HTFunctorImpl<R, HTNullType, ObjClass> : public HTFunctorImplBase<R>  
  17. {  
  18.     typedef R       ResultType;  
  19.   
  20.     virtual ResultType operator()(ObjClass* pObj) = 0;  
  21.     virtual HTFunctorImpl* Clone() const = 0;  
  22.     virtual ~HTFunctorImpl() {}  
  23. };  
  24.   
  25. // 一个参数版本  
  26. template <typename R, typename P1, class ObjClass>  
  27. struct HTFunctorImpl<R, TYPELIST_1(P1), ObjClass> : public HTFunctorImplBase<R>  
  28. {  
  29.     typedef R       ResultType;  
  30.     typedef typename HTTypeTraits<P1>::ParmType   Parm1;  
  31.   
  32.     virtual ResultType operator()(Parm1, ObjClass* pObj) = 0;  
  33.     virtual HTFunctorImpl* Clone() const = 0;  
  34.     virtual ~HTFunctorImpl() {}  
  35. };  
  36.   
  37. // 两个参数版本  
  38. template <typename R, typename P1, typename P2, class ObjClass>  
  39. struct HTFunctorImpl<R, TYPELIST_2(P1, P2), ObjClass> : public HTFunctorImplBase<R>  
  40. {  
  41.     typedef R       ResultType;  
  42.     typedef typename HTTypeTraits<P1>::ParmType   Parm1;  
  43.     typedef typename HTTypeTraits<P2>::ParmType Parm2;  
  44.   
  45.     virtual ResultType operator()(Parm1, Parm2, ObjClass* pObj) = 0;  
  46.     virtual HTFunctorImpl* Clone() const = 0;  
  47.     virtual ~HTFunctorImpl() {}  
  48. };  
  49.   
  50. // 可调用体(即封装的处理函数)为仿函数  
  51. template <class ParentFunctor, typename Fun, class ObjClass>  
  52. class HTFunctorHandler :   
  53.     public HTFunctorImpl  
  54.                 <   
  55.                 typename ParentFunctor::ResultType,  
  56.                 typename ParentFunctor::ParmList,  
  57.                 ObjClass  
  58.                 >  
  59. {  
  60.     typedef typename ParentFunctor::Impl    Base;  
  61. public:  
  62.     typedef typename Base::ResultType ResultType;  
  63.   
  64.     typedef typename Base::Parm1 Parm1;  
  65.     typedef typename Base::Parm1 Parm2;  
  66.   
  67.     HTFunctorHandler(const Fun& fun) : m_fun(fun) {}  
  68.     HTFunctorHandler* Clone() const { return new HTFunctorHandler(*this); }  
  69.   
  70.     ResultType operator()(ObjClass* pObj)   
  71.     { return m_fun(); }  
  72.   
  73.     ResultType operator()(Parm1 p1, ObjClass* pObj)  
  74.     { return m_fun(p1); }  
  75.   
  76.     ResultType operator()(Parm1 p1, Parm2 p2, ObjClass* pObj)  
  77.     { return m_fun(p1, p2); }  
  78.   
  79. private:  
  80.     Fun m_fun;  
  81. };  
  82.   
  83. // 可调用体(即封装的处理函数)为类成员函数,调用需传递对象指针  
  84. template <class ParentFunctor, typename Fun, class ObjClass>  
  85. class HTMemFunHandler :   
  86.     public HTFunctorImpl  
  87.                 <   
  88.                 typename ParentFunctor::ResultType,  
  89.                 typename ParentFunctor::ParmList,  
  90.                 ObjClass  
  91.                 >  
  92. {  
  93.     typedef typename ParentFunctor::Impl    Base;  
  94. public:  
  95.     typedef typename Base::ResultType ResultType;  
  96.   
  97.     typedef typename Base::Parm1 Parm1;  
  98.     typedef typename Base::Parm1 Parm2;  
  99.   
  100.     HTMemFunHandler(const Fun& fun) : m_fun(fun) {}  
  101.     HTMemFunHandler* Clone() const { return new HTMemFunHandler(*this); }  
  102.   
  103.     ResultType operator()(ObjClass* pObj)   
  104.     { return (pObj->*m_fun)(); }  
  105.   
  106.     ResultType operator()(Parm1 p1, ObjClass* pObj)   
  107.     { return (pObj->*m_fun)(p1); }  
  108.   
  109.     ResultType operator()(Parm1 p1, Parm2 p2, ObjClass* pObj)  
  110.     { return (pObj->*m_fun)(p1, p2); }  
  111.   
  112. private:  
  113.     Fun m_fun;  
  114. };  
  115.   
  116. // HTFunctor实现体  
  117. template <typename R, class TList = YKNullType, class ObjClass = YKEmptyType>  
  118. class HTFunctor  
  119. {  
  120.     typedef HTFunctorImpl<R, TList, ObjClass> Impl;  
  121. public:  
  122.     typedef R       ResultType;  
  123.     typedef TList   ParmList;  
  124.     typedef typename Impl::Parm1 Parm1;  
  125.     typedef typename Impl::Parm2 Parm2;  
  126.   
  127.     HTFunctor() : m_spImpl() {}  
  128.     HTFunctor(const HTFunctor& rhs) : m_spImpl(rhs.m_spImpl->Clone()) {}  
  129.     explicit HTFunctor(std::auto_ptr<Impl> spImpl) : m_spImpl(spImpl) {}  
  130.   
  131.     HTFunctor& operator=(const HTFunctor& rhs)  
  132.     {  
  133.         HTFunctor copy(rhs);  
  134.         Impl* p = m_spImpl.release();  
  135.         m_spImpl.reset(copy.m_spImpl.release());  
  136.         copy.m_spImpl.reset(p);  
  137.         return *this;  
  138.     }  
  139.   
  140.     template <typename Fun>  
  141.     HTFunctor(Fun fun)  
  142.         : m_spImpl(new   
  143.         HTSelect<  
  144.             HTIsSameType<ObjClass, HTEmptyType>::value,   
  145.             HTFunctorHandler<HTFunctor, Fun, ObjClass>,   
  146.             HTMemFunHandler<HTFunctor, Fun, ObjClass> >::Result(fun))  
  147.     {}  
  148.   
  149.     ResultType operator()(ObjClass* pObj = HT_NULL) {  
  150.         return (*m_spImpl)(pObj);  
  151.     }  
  152.   
  153.     ResultType operator()(Parm1 p1, ObjClass* pObj = HT_NULL) {  
  154.         return (*m_spImpl)(p1, pObj);  
  155.     }  
  156.   
  157.     ResultType operator()(Parm1 p1, Parm2 p2, ObjClass* pObj = HT_NULL) {  
  158.         return (*m_spImpl)(p1, p2, pObj);  
  159.     }  
  160.   
  161. private:  
  162.     std::auto_ptr<Impl> m_spImpl;  
  163. };  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值