编译阶段侦测可转换与继承性

你可以使用dynamic_cast,但这会影响运行阶段效率,而这个问题可以在编译阶段处理。这就是它的意义。

sizeof 是在编译阶段就可以搞定一切的操作符,它强大的威力在于它测侦测,举个例子来说:

int     fun();
sizeof (fun());

这是对int求sizeof,尽管你并未定义fun()。

侦测转换能力的想法是运用sizeof和重载。我们定义这样的重载:

BIG        Test(U);
Small    Test(...);

sizeof (Test(TNAME()))  ==   sizeof (BIG);

如你所见,这太棒了,传入可以转化为U的类型的时候,检测通过,否则失败,正是你想要的结果。
这里有个小问题,如果TNAME的构造函数不可访问怎么办,其实,正如上边所说,sizeof不计较实际是否有代码,它对表达式的判断采取“只看结果”的方式,于是我们可以这样改良这个测试策略

template     < class  T, class  U >
class  Conversion
{
    typedef    
char    Small;
    
static    class    Big        {char dummy[2];};
    
static    Small    Test(U);
    
static    Big        Test(...);
    
static    T        MakeT();    //稻草人方法
public:
    
enum    {exist = (sizeof(Test(MakeT())) == sizeof(Small))};
}
;

注意使用sizeof特点构造的稻草人函数技巧。

注意,我们是在测试可否转换,但其实负责转换的还是编译器,即使是在我们的测试策略里,也是使用了让编译器负责的方法。这也就是说int和double是可以互相转换的。于是我们可以添加一个互相转换标志:

template     < class  T, class  U >
class  Conversion
{
    typedef    
char    Small;
    
static    class    Big        {char dummy[2];};
    
static    Small    Test(U);
    
static    Big        Test(...);
    
static    T        MakeT();    //稻草人方法
public:
    
enum    {exist = (sizeof(Test(MakeT())) == sizeof(Small))};
    
//注意这行
    enum    {exist2Way = exists && Conversion<U,T>::exists};
}
;

对于非常调皮的使用者,他一定会跟你开这样的玩笑Conversion<int,int>::exists,为了对付这种情况,我们使用篇特化:

template     < class  T, class  U >
class  Conversion
{
    typedef    
char    Small;
    
static    class    Big        {char dummy[2];};
    
static    Small    Test(U);
    
static    Big        Test(...);
    
static    T        MakeT();    //稻草人方法
public:
    
enum    {exist = (sizeof(Test(MakeT())) == sizeof(Small))};
    
enum    {exist2Way = exists && Conversion<U,T>::exists};
    
//注意这行
    enum    {sameType = false};
}
;
template    
< class  T >
class     Conversion < T,T >
{
public:
    
enum    {exist = 1,exist2Way = 1,sameType = 1};
}
;

子类指针是可以任意向父类转换的,所以,我们如此判断class是否有继承关系:

#define  SUPERSUBCLASS(T,U)    (Conversion<const U*,const T*>::exists) && (!Conversion<const T*,const void*>::sameType)

如果U继承于T,那么U*可以向T*转换,而且T*和不能是void。关于第二点保证,是避免void*可以转换成目标指针的情况。

可以看出,这个判断里强调了const,这是怕无法通过对const型的测试,但是如果参数本身已经是const呢?
如果template代码实施const两次(对一个已经是const的类型而言),第二个cosnt会被忽略。Andrei如是说。

在loki里你可以使用<TypeManip.h>::SuperSubClass类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值