c++模板 SFINAE原则的疑惑
最近在看《C+++Templates》 这本书,关于下面的例子有些疑惑,请各位高手帮忙解答下,谢谢
程序代码:
#include <iostream>
using namespace std;
template<typename T>
class IsClassT
{
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C> static One test(int C::*);
template<typename C> static Two test(...);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
class MyClass
{
};
template <typename T>
void check()
{
if (IsClassT<T>::Yes) {
std::cout << " IsClassT " << std::endl;
}
else {
std::cout << " !IsClassT " << std::endl;
}
}
int main()
{
std::cout << "int: ";
check<int>();
std::cout << "MyClass: ";
check<MyClass>();
}
这个是书上的源代码,但是在vs2008下编译不通过。
将
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
改为:
static bool isClass()
{
return sizeof(IsClassT<T>::test<T>(0)) == 1;
}
可以顺利通过
1 请问这是为什么?
2 template<typename C> static One test(int C::*); 中参数的类型为
指向int 型的C 类的成员的指针
但是MyClass 中并没有int型的数据成员,为什么可以通过编译,并且顺利得到结果?
3 template<typename C> static One test(int C::*); 为什么需要写成模板函数?
改写成:static One test(int T::*); 为什么不行??
谢谢大家帮忙解答下!
[解决办法]
1 请问这是为什么?
---------------------
VS在这里存在不符合C++标准的行为,微软做的IDE本来就不怎么样。
sizeof(IsClassT<T>::test<T>(0)) == 1
改为:
sizeof(test<T>(0)) == 1
就可以了。
2 template<typename C> static One test(int C::*); 中参数的类型为
指向int 型的C 类的成员的指针
但是MyClass 中并没有int型的数据成员,为什么可以通过编译,并且顺利得到结果?
int C::*不过是一种指针类型,与C内是否有这样的数据成员无关,就像即使没有定义int对象,但你依然可以定义int*指针道理一样。
3 template<typename C> static One test(int C::*); 为什么需要写成模板函数?
改写成:static One test(int T::*); 为什么不行??
因为SFINAE是模板推导规则,这个规则只有存在其它合法选择的情况下才有效,去掉template<typename C>后,另一个合法选择 template<typename C> static Two test(...);消失了,所以就成为了编译错误。
[解决办法]
其实 #1 说的很详细了。