编译期侦测可转换性和继承性
Ø 理论基础:
Sizeof会直接传回大小,不需拖到执行期才评估。
Ø 原理:
合并运用sizeof和重载函数。提供两个重载函数:其中一个接受U,另一个接受“任何其他型别”。以型别T的暂时对象来调用这些函数,而“T是否可转换为U”正是我们想知道的。如果接受U的那个函数被调用,我们就知道T可转换为U;否则T便无法转换为U。为了知道哪一个函数被调用,我们对这两个重载函数安排大小不同的返回型别,并以sizeof来区分大小。型别本身无关紧要,重要的是其大小必须不同。
Ø 首先建立两个大小不同的型别:
typedef char Small;
class Big
{
char dummy[2];
};
Ø 建立两个重载函数:
Small Test(U);
Big Test(...);
注意:即使函数Test仅被声明而未被定义,也没有关系,因为sizeof并不对其引数求值。
Ø 检查T是否可以转换为U:
const bool convExists = sizeof(Test(T())) == sizeof(Small);
注意:如果T的default构造函数为private,则T()会编译失败。解决办法是以一个strawman function传回一个T对象,该函数不用被定义,因为sizeof中并不会真有任何表达式被求值。
T makeT();
const bool convExists = sizeof(Test(makeT())) == sizeof(Small);
Ø 把所有东西以class template包装起来,隐藏“型别推导”的所有细节,只暴露结果:
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::exists};
enum {sameType = false};
};
说明:exists表示T是否可以转换为U,exists2Way表示是否可以进行双向转换,sameType表示是否是相同型别。
通过Conversion的偏特化来实做出sameType:
template<class T>
class Conversion
{
public:
enum {exists = 1,exists2way = 1,sameType = 1};
};
Ø 通过定义宏来在编译期确定两个classes之间是否存在继承关系:
#define SUPERSUBCLASS(T,U) \
(Conversion<const U*,const T*>::exists && \
!Conversion<const T*,const void*>::sameType)
说明:只有三种情况下const U*可以转换为const T*:
1) T和U是同一种型别;
2) T是U的一个unambiguous public base;
3) T是void。
第三种情况在前述第二次测试中解决掉。可以通过定义以下宏把第一种情况也解决掉:
#define SUPERSUBCLASS_STRICT(T,U) \
(SUPERSUBCALSS(T,U) && \
!Conversion<const T,const U>::sameType)
说明:如果该宏为true,则表示U从T继承而来。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17014649/viewspace-612377/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17014649/viewspace-612377/