今天閑來無事,實現了一個簡版的boost::tuple作為練習,貼出來,僅供參考。
為了看起來清晰,tuple只支持3個參數,只要在注釋為A的地方繼續增加模板參數和構造函數的參數個數,就可以增加tuple元素的個數。
沒有type_trait,只為清晰,可讀。加了一點注釋,其中“遞歸”二字有時候說的不恰當,因為看似一個函數,實則不是一個函數。
仔細讀代碼吧。
輕拍
1 // 空類型,作為type_list的結束標記。
2
3 struct null_type
4 {
5 // 在tuple鏈的最尾端,構造一個null_type,對應type_list尾端的null_type.
6 null_type()
7 {}
8
9 // 這個構造函數完全是為了簡化cons的構造函數,其實是個“遞歸”結束條件。 A
10 template <class T1, class T2, class T3, class T4>
11 null_type(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
12 {}
13 };
14
15 // type_list + data_list聲明。
16 template <typename HH, typename TT>
17 struct cons;
18
19 // 用于在type_list中找到第N個類型,下標從1開始。
20 template <int N, typename _T>
21 struct element
22 {
23 typedef typename element<N-1, typename _T::tail_type>::type type;
24 };
25
26 // 所以特化為1,要是想從0開始,就特化0.
27 template <typename _T>
28 struct element<1, _T>
29 {
30 typedef typename _T::head_type type;
31 };
32
33 // 得到第N個類型對于的數據,注意是遞歸調用,對于不同的get_class<N>::get, get_class<N-1>::get
一直到 get_class<1>::get。
34 template <int N>
35 struct get_class
36 {
37 template <typename RET, typename HH, typename TT>
38 static RET get(cons<HH, TT>& c)
39 {
40 return get_class<N-1>::get<RET>(c.tail);
41 }
42 };
43
44 // 下標依然從1開始。
45 template <>
46 struct get_class<1>
47 {
48 template <typename RET, typename HH, typename TT>
49 static RET get(cons<HH, TT>& c)
50 {
51 return c.head;
52 }
53 };
54
55 // 繼續包裝,為了方便使用,得到第N個類型對應的數據。
56 template <int N, typename HH, typename TT>
57 typename element<N, cons<HH, TT> >::type&
58 get(cons<HH, TT>& c)
59 {
60 return get_class<N>::get<element<N, cons<HH, TT> >::type&>(c);
61 }
62
63 // type_list + data_list 的定義。
64 template <typename HH, typename TT>
65 struct cons
66 {
67 typedef HH head_type;
68 typedef TT tail_type;
69
70 head_type head;
71 tail_type tail;
72
73 // 構造函數,注意遞歸構造,遞歸結束條件是null_type的構造函數。 A
74 template <class T1, class T2, class T3>
75 cons( T1& t1, T2& t2, T3& t3, null_type)
76 : head (t1),
77 tail (t2, t3, null_type(), null_type())
78 {}
79
80 // 包裝的get方法,其實質還是調用全局的get,參數為*this。
81 template <int N>
82 typename element<N, cons<HH, TT> >::type
83 get()
84 {
85 return ::get<N>(*this);
86 }
87 };
88
89 // 構造type_list.主要是為了將序列式的模板參數轉化成type_list的樣子。 A
90 template <class T0, class T1, class T2>
91 struct map_tuple_to_cons
92 {
93 typedef cons<T0, typename map_tuple_to_cons<T1, T2, null_type>::type> type;
94 };
95 // 停止條件。
96 template <>
97 struct map_tuple_to_cons<null_type, null_type, null_type>
98 {
99 typedef null_type type;
100 };
101
102 // 包裝成tuple,其實就是一個type_list + data_list. A
103 template <class T0, class T1 = null_type, class T2 = null_type>
104 struct tuple : public map_tuple_to_cons<T0, T1, T2>::type
105 {
106 typedef typename map_tuple_to_cons<T0, T1, T2>::type base;
107
108 tuple(const T0& t0) : base(t0, null_type(), null_type(), null_type())
109 {
110 };
111
112 tuple(const T0& t0, const T1& t1) : base(t0, t1, null_type(),
113 null_type())
114 {
115 };
116
117 tuple(const T0& t0, const T1& t1, const T1& t2) : base(t0, t1, t2,
118 null_type())
119 {
120 };
121 };
122
123 // test.
124 int main()
125 {
126 tuple<int> x(3);
127 tuple<double, int> y(5.4, 2);
128
129 int x1 = get<1>(x);
130 double y1 = get<1>(y);
131 int y2 = get<2>(y);
132
133 x1 = x.get<1>();
134 y1 = y.get<1>();
135 y2 = y.get<2>();
136 }
posted on 2009-02-24 22:07
尹東斐 閱讀(1720)
評論(4) 編輯 收藏 引用