- 论坛徽章:
- 2
|
回复 6# liwangli1983
不需要T有int成员……
只要T是class/struct/union, 就可以有 X T::*(成员数据指针类型) 和 成员函数指针类型(orz,我已经忘记这货怎么写了……)
只是如果T没有int成员就无法指向……
- #include <time.h>
- template<int> struct error_message;
- template<typename T>
- char is_class(T /*1*/ T::*);
- template<typename T>
- long is_class(...);
- error_message<sizeof(is_class<tm>(0))> tm_;
- error_message<sizeof(is_class<double>(0))> double_;
复制代码 1. 被指向的类型其实是什么都无所谓……
一般用int,因为写起来短……
这里用的 T T::*,其实根本不可能存在一个类型T,它有一个类型为T的成员…… 这只是为了极端演示这里其实什么类型都无所谓…… T T::* 是否合法我也不知道……
保险还是用int T::*
2. 返回类型,我选char与long只是因为"char","long"长度相同…… 于是两个is_class就对得齐……
至于应该选什么类型,后面再说……
3. is_class<tm>(0), 因为tm是struct/class/union,所以有int tm::*类型(同上,我不知道tm tm::*是否合法……)。
那就够了,0可以转换成这个类型(一个成员指针)的空值,返回char的is_class比返回long的更匹配,于是sizeof返回sizeof(char)。
4. is_class<double>(0),int不是struct/class/union,所以不存在double int::*类型。
但is_class(int T::*) —— 或者上面的例子is_class(T T::*) —— 失败了也没关系…… 只要能找到一个成功的就行……
long is_class(...) 就是为了产生一个总是成功的东西…… 于是sizeof 返回sizeof(long)。
编译上面的代码,看编译错误就知道了。。。
回到2,返回类型…… 标准只保证sizeof(char)<=sizeof(long), 存在相等的情况……
于是,最通常的做法是让一个返回U,让另一个返回一个结构体,结构体包含U的数组,维度>=2。 于是两者大小肯定不相同了……
通常,U=char, 维度=2, 而且也不会直接返回U, 而是再搞一个结构体…… 于是就产生了:
- struct yes { char a; }; // 或者 char a[1];
- struct no { char a[2]; };
- template<typename T>
- yes is_class(int T::*);
- template<typename T>
- no is_class(...);
- #define IS_CLASS(T) ( sizeof(yes)==sizeof(is_class<T>(0)) )
复制代码 呃,我自己不太喜欢定义那两个类型…… 对不齐是一个原因……(强迫症……) 示例代码短,多写两行就多了一倍代码……
于是可以利用一些预定义的, 比如pair<int,int> 肯定比int大, tm也是……
但这样又需要包含utility或者time.h
于是…… 终极做法…… 返回U的数组的引用…… char最方便,因为sizeof(char)==1,可以少写一次sizeof……
- template<int> struct error_message;
- template<typename T>
- char (&is_class(int T::*))[1];
- template<typename T>
- char (&is_class(...))[2];
- #define IS_CLASS(T) ( 1==sizeof(is_class<T>(0)) )
- error_message<IS_CLASS(tm)> tm_;
- error_message<IS_CLASS(double)> double_;
复制代码 而且yes/no只能返回两种值, 直接返回引用可以支持多种值……
|
|