问题
如何识别两个模板参数T和U是否有继承关系?
原理
sizeof的威力
sizeof可以用于任何表达式,在编译期评估表达式类型的大小。因此,sizeof可以感知重载、模板实例化、转换规则,或任何可发生于C++表达式身上的机制。
识别类型转换能力机制
运用sizeof和重载函数。
1、函数重载提供选择分支
提供两个重载函数:一个接受目标类型U——1号函数,另一个接受其它任何类型——2号函数。用户用类型T来调用这些函数,用户想知道T是否可以转换成U。如果1号函数被调用,说明T可以转换成U,否则无法转换成U。
2、sizeof识别那个分支被调用
对上述两个重载函数安排大小不同的返回型别,用sizeof来区分其大小,通过大小就可以识别出那个函数被调用。
实现
1、建立两个返回值类型
using Small = char;
struct Big { char dummy[2]; };
2、声明两个重载函数
Small Test(U);
Big Test(...); //接受任意类型参数
3、sizeof识别
const bool convExists = sizeof(Test(T())) == sizeof(Small);
这里可能存在无法覆盖的点:
T没有无参构造函数或无参构造函数非public,则T()不合法。
改进:"稻草人函数"返回类型T
T makeT();
const bool convExists = sizeof(Test(makeT()) == sizeof(Small);
最终产物:
template<typename T, typename U>
struct Conversion
{
public:
enum
{
exists = sizeof(test(makeT())) == sizeof(Small)
};
enum
{
exists2way = exists and Conversion<U, T>::exists //双向转换
};
enum { sameType = false } ;
private:
using Small = char;
class Big{ char dummy[2]; };
static Small test(U) ;
static Big test(...);
static T makeT( ) ;
} ;
偏特化实现识别相同类型:
template<typename T>
struct Conversion<T, T>
{
enum
{
exists = true,
exists2way = true,
samerype = true
};
};