我们定义下面的一个类
template<typename T>
class IsFunctionT
{
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename U>
static One test(...);
template<typename U>
static Two test(U[]);//U (*)[1]);
public:
template<typename U>
static bool IsFT()
{
return (sizeof(IsFunctionT<T>::test<T>(0)) == sizeof(One));
}
};
template<typename T>
class IsFunctionT<T&>
{
public:
template<typename U>
static bool IsFT()
{
return false;
}
};
template<>
class IsFunctionT<void>
{
public:
template<typename U>
static bool IsFT()
{
return false;
}
};
template<>
class IsFunctionT<void const>
{
public:
template<typename U>
static bool IsFT()
{
return false;
}
};
使用的时候
typedef int ft();
bool a=IsFunctionT<ft>::IsFT<ft>();
让我们来仔细的看看上面的那个类
1
我们定义了两个私有的类型One和Two,分别是char和struct { char m[2];},这两个类型是为判断出我们采用了哪个函数服务的,不管在任何系统上这两个类型的size都应该是不同的.
2
我们还定义了3个静态的模板函数,其中两个是重载函数test,一个参数类型是...,另外的一个是U[],我们是通过显式的实例化这些模板函数.我们知道C++中是不能申明函数数组的(同样的还有void,void coonst和引用,所以采用了3个特例化来排除这几个类型).也就是说当我们实例化的时候传递的类型是函数类型,那么第二个test函数将匹配失败,编译器就会实例话第一个函数,这里用到了"substitution-failure-is-not-an-error" (SFINAE)原则.
所以当我们采用函数类型作为参数调用IsFunctionT::IsFT的时候,函数内部调用sizeof(IsFunctionT::test<U>(0))的test版本就是test(...)的版本,所以得到的sizeof就等于sizeof(One).反之,如果是非函数类型,那么就是调用test(U[]),将0转化成需要的数据,这样得到的sizeof就不等于sizeof(One).
我们就得到了判断类型是否是函数的方法.
PS:<<C++ Templates>> is <<C++ Templates: The Complete Guide>>

浙公网安备 33010602011771号