|
在水木C++版,有人提出如何针对"基类是xx类的类型"进行特化。这里面的关键 是理解这样几件事情:
1. 模板的特化 2. 如何在编译期判断xx是xx的基类
我们使用了这样一个type traits:
1 2 template <typename B, typename D> 3 struct is_base_of // check if B is a base of D 4 { 5 typedef char yes[1]; 6 typedef char no[2]; 7 8 static yes; test(B*); 9 static no; test( ); 10 11 static D* get(void); 12 13 static const bool value = sizeof(test(get())) == sizeof(yes); 14 }; 15
关键是理解struct is_base_of的最后一行,涉及对sizeof的理解:
The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is an unevaluated operand (Clause 5), or a parenthesized type-id. --- Working Draft, Standard for Programming Language C++ (5.3.3)
重点就是test(get())是unevaluated,编译期可以推断出该表达式的类型,如果 D是B的子类,则`static yes; test(B*);`是更好的匹配,否则就是另一个,而 它们返回值类型的大小不一样,藉此可以判断D是否B的子类。
下面是模板类的代码:
1 2 struct Base 3 { 4 }; 5 6 template <typename T, bool nouse=is_base_of<Base, T>::value> 7 class ATemplate 8 { 9 public: 10 ATemplate( ) 11 { 12 printf( "no\n" ); 13 } 14 ~ATemplate( ) 15 { 16 17 } 18 }; 19 20 21 template <typename T> 22 class ATemplate<T,true> 23 { 24 public: 25 ATemplate( ) 26 { 27 printf( "yes\n" ); 28 } 29 ~ATemplate( ) 30 { 31 32 } 33 }; 34 35 struct D:public Base 36 { 37 38 }; 39 struct C 40 { 41 42 }; 43 44 45 int main( ) 46 { 47 ATemplate<C> t; 48 ATemplate<D> t1; 49 return 0; 50 } 51
结果如下:
$ ./t no yes
| |