首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

c++模板 SFINAE准则的疑惑

2013-04-20 
c++模板 SFINAE原则的疑惑最近在看《C+++Templates》 这本书,关于下面的例子有些疑惑,请各位高手帮忙解答下,

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 说的很详细了。

引用:
这个还是有点疑惑,int C::*是一种指针类型,这个知道,但是指针也有指向的类型吧?
int C::* 与 double C::*应该是不一样的吧? 一个表示指向类C中的int型的数据成员,一个表示指向类C中
的double 型的数据成员。类C中都没有int型的数据成员,不明白为什么可以通过。
继续追问下,检测类C中是否有int型的数据成员,该怎么写呢?……

没有通用的方法检测某类是否存在 int 型数据成员。不过难点不在于如何检测某类某数据成员是否为 int 类型,而在于自动枚举某类所有数据成员,后者没有 c++ 支持的标准做法,如果想做的话,八成得使用编译器扩展。
  
引用:
是不是该这样理解,SFINAE是模板推导规则, 因为在一个类模板中
改写成:static One test(int T::*)后,通过IsClassT<int>::的形式来调用,
这个时候,static One test(int T::*)相当于 static One test(int int::*)没有使用模板推导?……

基本就是这样吧。
[解决办法]
引用:
谢谢楼上两位的解答,还有点疑惑
C/C++ code?12345678910111213class MyClass{public:    int _a;    double _b;}; void main(){    int MyClass::* p1 = &amp;MyClass::_a;    int MyClass::* p2 = &amp;MyClass::_b……

 int MyClass::* p1 = 0 ; 
double MyClass::* p1 = 0 ;
都可以...

热点排行