我的C++实践(9):一个完整的类型区分框架

    (1)辨别基本类型:IsFundaT<T>及MK_FUNDA_TYPE(T)。
    独特构造:基本类型都是已知的,并且个数有限,因此直接用特化来实现。定义一个基本模板表示非基本类型,然后结合宏MK_FUNDA_TYPE(T)来对各个基本类型提供特化,以表示它们是基本类型,用宏主要是为了使代码更简洁。

    (2)辨别函数类型:IsFunctionT<T>。
    独特构造:数组元素的类型不能为void类型、引用类型或函数类型。因此可构造一个测试用的成员函数模板,函数形参为模板参数的数组类型指针,这样数组元素就不能接受函数类型。同时提供该成员另一个重载版本,以应付T是函数类型的情况(SFINAE原则),对有干扰的void类型和引用类型提供特化以表示它们不是函数类型,这样就可以辨别T了。

    代码中的U (*)[1]是一个指向数组U[1]的指针,U是数组元素的类型。可见这里的U不能为函数、引用及void类型。当U为函数、引用及void以外的其他类型时,sizeof就会使用这个版本的test函数,返回的Two的字节数2,则Yes为0,表示非函数类型。当为引用或void类型时,会使用特化版本,设置Yes为0。当为函数类型时,sizeof中的Test匹配有数组指针的那个Test时不会成功,但它能匹配另一个返回One为1个字节的test版本,根据SFINAE原则,它会使用这个版本的test,Yes设置为1。注意这里test只需声明,无需定义,因为sizeof并不会真正调用并执行该函数,不需要函数代码定义,它只是计算返回类型的字节数。
    当然,我们还可以用其他的独特构造来实现,比如只有对函数类型,F&(指向函数类型的引用)才能转化为F*。通过判断能否把一个F&转化为F*,也可辨别出F是否是函数类型。
    (3)辨别复合类型:CompoundT<T>::IsPtrT,IsRefT,IsArrayT,IsFuncT,IsPtrMemT,这包括指针类型、引用类型、数组类型、函数类型、成员指针类型。
    独特构造:这些类型局部已知,且个数有限,可直接用局部特化来实现。对函数类型则可复用上面的IsFunctionT<T>。

    这里还对给定参数个数的函数类型定义了局部特化。这些特化不提供也没问题,因为代码中是使用上面的IsFunctionT<T>来辨别函数类型的。但提供这些特化也不冲突,提供它们的好处是我们还可以访问函数类型中的参数类型和返回类型。从中我们也可以看出,不能通过直接的局部特化来辨别一般的函数类型,因为函数的参数个数不确定,这样就需要为每种参数个数的函数类型都提供局部特化,会有无数个局部特化。
    (4)辨别类类型(class,struct,union):IsClassT<T>。
    独特构造:只有类类型才有成员指针。因此可构造一个测试用的成员函数模板,函数形参为模板参数的一个成员指针,这样模板参数就只能为类类型了。同时提供该成员另一个重载版本,以应付T是非类类型时的情况(SFINAE原则)。

    (5)辨别枚举类型。IsEnumT<T>。一种实现是排除上面所有的类型,剩下的就是枚举类型了。我们也可以针对枚举类型的独特构造来提供另一种实现。
    独特构造:枚举类型可以隐式转型为整型,这需要排除其他能够转型为整型的基本类型、指针类型、引用类型、成员指针类型的干扰。可用特化,也可用重载解析来实现。定义一个可转型为模板参数的类模板,和一个测试用的函数,为各种受干扰的类型提供该函数的重载版本。通过传递一个可转型的对象给测试函数,转型为模板参数T后,就会运用重载解析来调用相应的重载版本,以辨别出枚举类型。

    IsEnumT<T>中,先排除T是基本类型、引用类型、指针类型、成员指针类型的情况。在sizeof运算中,enum_check接受一个ConsumeUDC<T>的临时对象作为参数,由于ConsumeUDC<T>中自定义了转型运算符,因此它会转型为一个T型对象,但T如果是函数类型、数组类型或void类型,则不允许转型(即调用其中的特化版本),这样根据重载解析,enum_check将会选择最后的那个省略号版本,sizeof返回2,Yes设置为0。剩下的只有类类型和枚举类型了。如果T是类类型,则允许转型,转型过来的T型对象只能匹配那个省略号的test版本,Yes被设置为0。注意即使T自定义了一个到整型的转型运算符,也不会再考虑,因为在重载解析的匹配中,只允许有一次的自定义转型。最后,当T是枚举类型时,ConsumeUDC<T>对象自定义转型为T型对象,然后T会类型提升为整型(这个是自动的隐式转型,不是自定义的),从而enum_check匹配一个整型参数的版本,sizeof返回1,Yes设置为1。可见,这个IsEnumT实现比较复杂,这里主要是为了展示各种高级C++语法特性的应用,包括重载解析、模板特化、类型转换(自定义的转型及隐式的类型提升)等。
    (5)完整的类型区分实现。

    (6)测试代码。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值