【C++泛型编程】编译期可转换性和继承性检测
来源:互联网 发布:大疆无人机软件 编辑:程序博客网 时间:2024/04/28 09:30
问题:在设计模板函数和模板类时,面对两个型别T和U,我们怎么判断U是否继承自T呢?如果能在编译器判断这样的关系,可以优化泛型编程的函数。在编译器发现这样的关系,就意味着可以不使用dynamic_cast,它会损耗执行效率。
继承性检测可以转化成一个更一般的问题:检测任意型别T是否可以自动转化成型别U?
解决方法:可以使用运用sizeof和函数重载的方法来检测这种可转换性。编写两个重载函数:一个接受U(U代表转换目标)的函数,另一个接受“任何型别”的函数。用型别为T的暂时对象来调用这些重载函数,而“T是否可以转化为U”是我们想知道的。如果接受U的那个函数被调用,就可以判断T可以转换为U;否则T无法转换为U。为了知道哪个函数被调用,这两个重载函数以不同大小的型别返回,用sizeof来区分其大小。
具体方法如下:
第一步:定义两个不同大小的型别:
第二步:定义两个重载函数
现在在Conversion中定义两个常数:
a.exists2Way:表示T和U之间是否可以双向转换。
下面通过Conversion的偏特化来定义sameType的版本
判断两个类是否存在继承关系,可以用如下的方式:
如果U是public继承自T,或T和U是同一个型别,那么SUPERSUBCLASS(T,U)返回true.
当SUPERSUBCLASS(T,U)对const U* 和const T *作可转换性检测时,只有三种情况const U *可以隐式的转换为const T*:
a.T和U是同一个型别
b.T是U的一个public base
c.T 是void
第三种情况可以在前面的!Conversion<const T*,const void*>::sameType处理掉。第一和第二种情况需要用下面更严谨的方法:
继承性检测可以转化成一个更一般的问题:检测任意型别T是否可以自动转化成型别U?
解决方法:可以使用运用sizeof和函数重载的方法来检测这种可转换性。编写两个重载函数:一个接受U(U代表转换目标)的函数,另一个接受“任何型别”的函数。用型别为T的暂时对象来调用这些重载函数,而“T是否可以转化为U”是我们想知道的。如果接受U的那个函数被调用,就可以判断T可以转换为U;否则T无法转换为U。为了知道哪个函数被调用,这两个重载函数以不同大小的型别返回,用sizeof来区分其大小。
具体方法如下:
第一步:定义两个不同大小的型别:
typedef char Small; class Big{char dummy[2];};并且很明显sizeof(Small)<sizeof(Big);
第二步:定义两个重载函数
Small Test(U);Big Test(...); //可以接受任何其他对象的函数现在我们可以传递一个T对象给Test()函数,并用sizeof来判断其返回值的大小。
const bool convExists=sizeof(Test(T()))==sizeof(Small);T()会调用T对象的默认构造函数,万一T的默认构造函数定义为private,那么T()就会编译失败,所以需要换一种方法来生成对象,用函数的返回值来实现,如下:
T MakeT();//不实现const bool convExists=sizeof(Test(MakeT()))==sizeof(Small);下面用类模板封装起来:
template<class T,class U>class Conversion{typedef char Small;class Big{char dummy[2]};static Small Test(U);static Big Test(...);static T makeT();public:enum{exists=sizeof(Test(MakeT()))==sizeof(Small)};};测试代码如下:
Conversion<double,int>::exists;
现在在Conversion中定义两个常数:
a.exists2Way:表示T和U之间是否可以双向转换。
b.sameType:如果T和U是相同的型别,这个值为true;
template<class T,class U>class Conversion{typedef char Small;class Big{char dummy[2]};static Small Test(U);static Big Test(...);static T makeT();public:enum{exists=sizeof(Test(MakeT()))==sizeof(Small)};enum{exists2Way=exists&&Conversion<U,T>::exists};enum{sameType=false};};
下面通过Conversion的偏特化来定义sameType的版本
template<class T>class Conversion<T,T>{public:enum{exists=1,exists2Way=1,sameType=1};};
判断两个类是否存在继承关系,可以用如下的方式:
#define SUPERSUBCLASS(T,U) \(Conversion<const U *,const T *>::exists&& \ //这里函数调用参数次序交换了,表示U是否可以转换为T,即判断T是父类,U是子类。 !Conversion<const T*,const void*>::sameType)
如果U是public继承自T,或T和U是同一个型别,那么SUPERSUBCLASS(T,U)返回true.
当SUPERSUBCLASS(T,U)对const U* 和const T *作可转换性检测时,只有三种情况const U *可以隐式的转换为const T*:
a.T和U是同一个型别
b.T是U的一个public base
c.T 是void
第三种情况可以在前面的!Conversion<const T*,const void*>::sameType处理掉。第一和第二种情况需要用下面更严谨的方法:
#define SUPERSUBCLASS_STRICT(T,U) \(SUPERSUBCLASS(T,U)&& \!Conversion<const T,const U>::sameType)
- 【C++泛型编程】编译期可转换性和继承性检测
- 编译期对可转换型和继承性的侦测
- 【C++泛型编程】编译期错误检测
- 模板之编译器侦测可转换型和继承性
- 编译阶段侦测可转换与继承性
- 编译期判断类的继承性
- C+中继承和部分泛型编程
- 【C#】C#OOP编程之继承性
- C#2.0泛型编程之强制类型转换、继承和泛型
- C++ FAQ学习笔记 21章 继承 — 适当的继承和可置换性
- 编译期检测错误(compile-time assertions)
- C语言编程常见问题解答之可移植性
- openssl编程入门(含完整可编译和运行示例)
- 运行期断言和编译期断言
- 编译期优化和运行期优化
- 编译期和运行期区别
- Java编译期和运行期 & JVM
- ios 编译期和运行期
- 代理下载android sdk
- 笔记___《跋涉不止》中的 技术牛人 狂人 强人
- Genesys开发板生成带bootloader的bit文件(可以直接从PROM中启动)
- #舍得Share#php开发笔记-通过IP区分不同国家的用户
- Android反编译工具简介
- 【C++泛型编程】编译期可转换性和继承性检测
- iframe用法精析
- 关于android系统图像特效处理之光照效果
- 十年
- DX10的几何着色器
- java面试笔试题大汇总 ~很全面
- Win7下搭建Python开发环境[py+pyqt4+Eric4]
- 关于android系统图像特效处理之锐化效果
- DX10使用cube纹理实现天空盒