在水木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
摘自 卡列寧的微笑