当前位置:编程学习 > C/C++ >>

软件架构设计之Utility模块——Functor

一:前言
         现在要实作一个泛化仿函数,泛化仿函数是将“请求(函数)封装起来”,存储与对象之中,该对象是具有“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
[cpp]  
<span style="font-weight: normal;"><span style="font-size:14px;">template <class T, class U>  
struct HTTypeList  
{  
    typedef T Head;  
    typedef U Tail;  
};</span></span>  
这是typelist的基本实作(只需两个类型),现在问题是如何把n个类型连成链表。看下面这个例子就明白了
[cpp]  
typedef HTTypeList<char, HTTypeList<int, int> >  
(利用模板参数推导,而且是编译器自动产生,而不是运行期哦),这样两个以上的参数都解决了。
         现在问题如何定义一个参数的typelist。方法是,第二个模板参数设为NullType(空类型),这样每个typelist都以NullType结尾,相当于C字符串的\0功能。看NullType的实作:
[cpp]  
class HTNullType {};  
         接着就要生产typelist了(一个参数,两个参数,三个参数……)。这里用到宏,暂且定义4个typelist。
[cpp]  
#define TYPELIST_1(T1) UTIL::HTTypeList<T1, UTIL::HTNullType>  
#define TYPELIST_2(T1, T2) UTIL::HTTypeList<T1, TYPELIST_1(T2) >  
#define TYPELIST_3(T1, T2, T3) UTIL::HTTypeList<T1, TYPELIST_2(T2, T3) >  
#define TYPELIST_4(T1, T2, T3, T4) UTIL::HTTypeList<T1, TYPELIST_3(T2, T3, T4) >  
 
另外要解决的问题是,函数参数该是值类型(内部内型)还是引用类型(对于对象)。选择合适的类型显然能提高程序速度,你肯定不想传递大对象参数时而要额外拷贝。接下来这个东西就要登场了——(HTTypeTraits)
三:HTTypeTraits
         可用于“编译期根据型别作判断”的泛型技术。大家也可参看boost中的type traits。
[cpp]  
// 判断T及U是否标示同一个类型  
template <typename T, typename U>  
struct HTIsSameType  
{  
private:  
    template<typename>  
    struct In   
    { enum { value = false }; };  
  
    template<>  
    struct In<T>  
    { enum { value = true };  };  
  
public:  
    enum { value = In<U>::value };  
};  
[cpp] 
// 依flag选择两个类型中的一个,true为T,false为U  
template <bool flag, typename T, typename U>  
struct HTSelect  
{  
private:  
    template<bool>  
    struct In   
    { typedef T Result; };  
  
    template<>  
    struct In<false>  
    { typedef U Result; };  
  
public:  
    typedef typename In<flag>::Result Result;  
};  
[cpp]  
// 编译期bool型  
typedef char HTYes;  
struct HTNo { char padding[8]; };  
  
// 型别映射为型别,用于模板函数的偏特化,C++标准模板函数不能偏特化  
template <typename T>  
struct HTType2Type { typedef T Type; };  
  
// 判断T是否为类  
template <typename T>  
struct HTIsClass  
{  
    // U为类的话,会具现化此重载函数,因为参数为函数指针,即指向成员的函数指针  
    template <typename U> static HTYes IsClassTest(void(U::*)(void));  
    // U为非类,会具现化此重载函数  
    // C++标准:只有当其它所有的重载版本都不能匹配时,具有任意参数列表的重载版本才会被匹配  
    template <typename U> static HTNo IsClassTest(...);  
  
    // 对于sizeof,表达式不会被真正求值,编译器只推导出表达式的返回结果的型别,因此只需函数的声明即可  
    static const bool value = sizeof(IsClassTest<T>(0)) = sizeof(HTYes);  
};  
  
// 判断T是否为引用类型  
template <typename T>  
struct HTIsReference  
{  
    template <typename U> static HTYes IsReference(HTType2Type<U&>);  
    template <typename U> static HTNo IsReference(...);  
  
    static const bool value= sizeof(IsReference(HTType2Type<T>())) == sizeof(HTYes);  
};  
  
template <typename T>  
class HTTypeTraits  
{  
  
public:  
    enum {   
        isVoid =   
        HTIsSameType<T, void>::value          ||  
        HTIsSameType<T, const void>::value    ||  
        HTIsSameType<T, volatile void>::value ||  
        HTIsSameType<T, const volatile void>::value  
    };  
  
    enum { isReference = HTIsReference<T>::value };  
  
private:  
    template<bool IsRef>  
    struct AdjReference  
    {  
        template<typename U>  
        struct In { typedef U const & Result; };  
    };  
  
    tem
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,