rev |
line source |
nuclear@0
|
1 // A very small replacement for boost::tuple
|
nuclear@0
|
2 // (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net]
|
nuclear@0
|
3
|
nuclear@0
|
4 #ifndef BOOST_TUPLE_INCLUDED
|
nuclear@0
|
5 #define BOOST_TUPLE_INCLUDED
|
nuclear@0
|
6
|
nuclear@0
|
7 namespace boost {
|
nuclear@0
|
8 namespace detail {
|
nuclear@0
|
9
|
nuclear@0
|
10 // Represents an empty tuple slot (up to 5 supported)
|
nuclear@0
|
11 struct nulltype {};
|
nuclear@0
|
12
|
nuclear@0
|
13 // For readable error messages
|
nuclear@0
|
14 struct tuple_component_idx_out_of_bounds;
|
nuclear@0
|
15
|
nuclear@0
|
16 // To share some code for the const/nonconst versions of the getters
|
nuclear@0
|
17 template <bool b, typename T>
|
nuclear@0
|
18 struct ConstIf {
|
nuclear@0
|
19 typedef T t;
|
nuclear@0
|
20 };
|
nuclear@0
|
21
|
nuclear@0
|
22 template <typename T>
|
nuclear@0
|
23 struct ConstIf<true,T> {
|
nuclear@0
|
24 typedef const T t;
|
nuclear@0
|
25 };
|
nuclear@0
|
26
|
nuclear@0
|
27 // Predeclare some stuff
|
nuclear@0
|
28 template <typename, unsigned, typename, bool, unsigned> struct value_getter;
|
nuclear@0
|
29
|
nuclear@0
|
30 // Helper to obtain the type of a tuple element
|
nuclear@0
|
31 template <typename T, unsigned NIDX, typename TNEXT, unsigned N /*= 0*/>
|
nuclear@0
|
32 struct type_getter {
|
nuclear@0
|
33 typedef type_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,N> next_elem_getter;
|
nuclear@0
|
34 typedef typename next_elem_getter::type type;
|
nuclear@0
|
35 };
|
nuclear@0
|
36
|
nuclear@0
|
37 template <typename T, unsigned NIDX, typename TNEXT >
|
nuclear@0
|
38 struct type_getter <T,NIDX,TNEXT,NIDX> {
|
nuclear@0
|
39 typedef T type;
|
nuclear@0
|
40 };
|
nuclear@0
|
41
|
nuclear@0
|
42 // Base class for all explicit specializations of list_elem
|
nuclear@0
|
43 template <typename T, unsigned NIDX, typename TNEXT >
|
nuclear@0
|
44 struct list_elem_base {
|
nuclear@0
|
45
|
nuclear@0
|
46 // Store template parameters
|
nuclear@0
|
47 typedef TNEXT next_type;
|
nuclear@0
|
48 typedef T type;
|
nuclear@0
|
49
|
nuclear@0
|
50 static const unsigned nidx = NIDX;
|
nuclear@0
|
51 };
|
nuclear@0
|
52
|
nuclear@0
|
53 // Represents an element in the tuple component list
|
nuclear@0
|
54 template <typename T, unsigned NIDX, typename TNEXT >
|
nuclear@0
|
55 struct list_elem : list_elem_base<T,NIDX,TNEXT>{
|
nuclear@0
|
56
|
nuclear@0
|
57 // Real members
|
nuclear@0
|
58 T me;
|
nuclear@0
|
59 TNEXT next;
|
nuclear@0
|
60
|
nuclear@0
|
61 // Get the value of a specific tuple element
|
nuclear@0
|
62 template <unsigned N>
|
nuclear@0
|
63 typename type_getter<T,NIDX,TNEXT,N>::type& get () {
|
nuclear@0
|
64 value_getter <T,NIDX,TNEXT,false,N> s;
|
nuclear@0
|
65 return s(*this);
|
nuclear@0
|
66 }
|
nuclear@0
|
67
|
nuclear@0
|
68 // Get the value of a specific tuple element
|
nuclear@0
|
69 template <unsigned N>
|
nuclear@0
|
70 const typename type_getter<T,NIDX,TNEXT,N>::type& get () const {
|
nuclear@0
|
71 value_getter <T,NIDX,TNEXT,true,N> s;
|
nuclear@0
|
72 return s(*this);
|
nuclear@0
|
73 }
|
nuclear@0
|
74
|
nuclear@0
|
75 // Explicit cast
|
nuclear@0
|
76 template <typename T2, typename TNEXT2 >
|
nuclear@0
|
77 operator list_elem<T2,NIDX,TNEXT2> () const {
|
nuclear@0
|
78 list_elem<T2,NIDX,TNEXT2> ret;
|
nuclear@0
|
79 ret.me = (T2)me;
|
nuclear@0
|
80 ret.next = next;
|
nuclear@0
|
81 return ret;
|
nuclear@0
|
82 }
|
nuclear@0
|
83
|
nuclear@0
|
84 // Recursively compare two elements (last element returns always true)
|
nuclear@0
|
85 bool operator == (const list_elem& s) const {
|
nuclear@0
|
86 return (me == s.me && next == s.next);
|
nuclear@0
|
87 }
|
nuclear@0
|
88 };
|
nuclear@0
|
89
|
nuclear@0
|
90 // Represents a non-used tuple element - the very last element processed
|
nuclear@0
|
91 template <typename TNEXT, unsigned NIDX >
|
nuclear@0
|
92 struct list_elem<nulltype,NIDX,TNEXT> : list_elem_base<nulltype,NIDX,TNEXT> {
|
nuclear@0
|
93 template <unsigned N, bool IS_CONST = true> struct value_getter {
|
nuclear@0
|
94 /* just dummy members to produce readable error messages */
|
nuclear@0
|
95 tuple_component_idx_out_of_bounds operator () (typename ConstIf<IS_CONST,list_elem>::t& me);
|
nuclear@0
|
96 };
|
nuclear@0
|
97 template <unsigned N> struct type_getter {
|
nuclear@0
|
98 /* just dummy members to produce readable error messages */
|
nuclear@0
|
99 typedef tuple_component_idx_out_of_bounds type;
|
nuclear@0
|
100 };
|
nuclear@0
|
101
|
nuclear@0
|
102 // dummy
|
nuclear@0
|
103 list_elem& operator = (const list_elem& other) {
|
nuclear@0
|
104 return *this;
|
nuclear@0
|
105 }
|
nuclear@0
|
106
|
nuclear@0
|
107 // dummy
|
nuclear@0
|
108 bool operator == (const list_elem& other) {
|
nuclear@0
|
109 return true;
|
nuclear@0
|
110 }
|
nuclear@0
|
111 };
|
nuclear@0
|
112
|
nuclear@0
|
113 // Represents the absolute end of the list
|
nuclear@0
|
114 typedef list_elem<nulltype,0,int> list_end;
|
nuclear@0
|
115
|
nuclear@0
|
116 // Helper obtain to query the value of a tuple element
|
nuclear@0
|
117 // NOTE: This can't be a nested class as the compiler won't accept a full or
|
nuclear@0
|
118 // partial specialization of a nested class of a non-specialized template
|
nuclear@0
|
119 template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST, unsigned N>
|
nuclear@0
|
120 struct value_getter {
|
nuclear@0
|
121
|
nuclear@0
|
122 // calling list_elem
|
nuclear@0
|
123 typedef list_elem<T,NIDX,TNEXT> outer_elem;
|
nuclear@0
|
124
|
nuclear@0
|
125 // typedef for the getter for next element
|
nuclear@0
|
126 typedef value_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,
|
nuclear@0
|
127 IS_CONST, N> next_value_getter;
|
nuclear@0
|
128
|
nuclear@0
|
129 typename ConstIf<IS_CONST,typename type_getter<T,NIDX,TNEXT,N>::type>::t&
|
nuclear@0
|
130 operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) {
|
nuclear@0
|
131
|
nuclear@0
|
132 next_value_getter s;
|
nuclear@0
|
133 return s(me.next);
|
nuclear@0
|
134 }
|
nuclear@0
|
135 };
|
nuclear@0
|
136
|
nuclear@0
|
137 template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST>
|
nuclear@0
|
138 struct value_getter <T,NIDX,TNEXT,IS_CONST,NIDX> {
|
nuclear@0
|
139 typedef list_elem<T,NIDX,TNEXT> outer_elem;
|
nuclear@0
|
140
|
nuclear@0
|
141 typename ConstIf<IS_CONST,T>::t& operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) {
|
nuclear@0
|
142 return me.me;
|
nuclear@0
|
143 }
|
nuclear@0
|
144 };
|
nuclear@0
|
145 };
|
nuclear@0
|
146
|
nuclear@0
|
147 // A very minimal implementation for up to 5 elements
|
nuclear@0
|
148 template <typename T0 = detail::nulltype,
|
nuclear@0
|
149 typename T1 = detail::nulltype,
|
nuclear@0
|
150 typename T2 = detail::nulltype,
|
nuclear@0
|
151 typename T3 = detail::nulltype,
|
nuclear@0
|
152 typename T4 = detail::nulltype>
|
nuclear@0
|
153 class tuple {
|
nuclear@0
|
154
|
nuclear@0
|
155 template <typename T0b,
|
nuclear@0
|
156 typename T1b,
|
nuclear@0
|
157 typename T2b,
|
nuclear@0
|
158 typename T3b,
|
nuclear@0
|
159 typename T4b >
|
nuclear@0
|
160 friend class tuple;
|
nuclear@0
|
161
|
nuclear@0
|
162 private:
|
nuclear@0
|
163
|
nuclear@0
|
164 typedef detail::list_elem<T0,0,
|
nuclear@0
|
165 detail::list_elem<T1,1,
|
nuclear@0
|
166 detail::list_elem<T2,2,
|
nuclear@0
|
167 detail::list_elem<T3,3,
|
nuclear@0
|
168 detail::list_elem<T4,4,
|
nuclear@0
|
169 detail::list_end > > > > > very_long;
|
nuclear@0
|
170
|
nuclear@0
|
171 very_long m;
|
nuclear@0
|
172
|
nuclear@0
|
173 public:
|
nuclear@0
|
174
|
nuclear@0
|
175 // Get a specific tuple element
|
nuclear@0
|
176 template <unsigned N>
|
nuclear@0
|
177 typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () {
|
nuclear@0
|
178 return m.template get<N>();
|
nuclear@0
|
179 }
|
nuclear@0
|
180
|
nuclear@0
|
181 // ... and the const version
|
nuclear@0
|
182 template <unsigned N>
|
nuclear@0
|
183 const typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () const {
|
nuclear@0
|
184 return m.template get<N>();
|
nuclear@0
|
185 }
|
nuclear@0
|
186
|
nuclear@0
|
187
|
nuclear@0
|
188 // comparison operators
|
nuclear@0
|
189 bool operator== (const tuple& other) const {
|
nuclear@0
|
190 return m == other.m;
|
nuclear@0
|
191 }
|
nuclear@0
|
192
|
nuclear@0
|
193 // ... and the other way round
|
nuclear@0
|
194 bool operator!= (const tuple& other) const {
|
nuclear@0
|
195 return !(m == other.m);
|
nuclear@0
|
196 }
|
nuclear@0
|
197
|
nuclear@0
|
198 // cast to another tuple - all single elements must be convertible
|
nuclear@0
|
199 template <typename T0b, typename T1b,typename T2b,typename T3b, typename T4b>
|
nuclear@0
|
200 operator tuple <T0b,T1b,T2b,T3b,T4b> () const {
|
nuclear@0
|
201 tuple <T0b,T1b,T2b,T3b,T4b> s;
|
nuclear@0
|
202 s.m = (typename tuple <T0b,T1b,T2b,T3b,T4b>::very_long)m;
|
nuclear@0
|
203 return s;
|
nuclear@0
|
204 }
|
nuclear@0
|
205 };
|
nuclear@0
|
206
|
nuclear@0
|
207 // Another way to access an element ...
|
nuclear@0
|
208 template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
|
nuclear@0
|
209 inline typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
|
nuclear@0
|
210 tuple<T0,T1,T2,T3,T4>& m) {
|
nuclear@0
|
211 return m.template get<N>();
|
nuclear@0
|
212 }
|
nuclear@0
|
213
|
nuclear@0
|
214 // ... and the const version
|
nuclear@0
|
215 template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
|
nuclear@0
|
216 inline const typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
|
nuclear@0
|
217 const tuple<T0,T1,T2,T3,T4>& m) {
|
nuclear@0
|
218 return m.template get<N>();
|
nuclear@0
|
219 }
|
nuclear@0
|
220
|
nuclear@0
|
221 // Constructs a tuple with 5 elements
|
nuclear@0
|
222 template <typename T0,typename T1,typename T2,typename T3,typename T4>
|
nuclear@0
|
223 inline tuple <T0,T1,T2,T3,T4> make_tuple (const T0& t0,
|
nuclear@0
|
224 const T1& t1,const T2& t2,const T3& t3,const T4& t4) {
|
nuclear@0
|
225
|
nuclear@0
|
226 tuple <T0,T1,T2,T3,T4> t;
|
nuclear@0
|
227 t.template get<0>() = t0;
|
nuclear@0
|
228 t.template get<1>() = t1;
|
nuclear@0
|
229 t.template get<2>() = t2;
|
nuclear@0
|
230 t.template get<3>() = t3;
|
nuclear@0
|
231 t.template get<4>() = t4;
|
nuclear@0
|
232 return t;
|
nuclear@0
|
233 }
|
nuclear@0
|
234
|
nuclear@0
|
235 // Constructs a tuple with 4 elements
|
nuclear@0
|
236 template <typename T0,typename T1,typename T2,typename T3>
|
nuclear@0
|
237 inline tuple <T0,T1,T2,T3> make_tuple (const T0& t0,
|
nuclear@0
|
238 const T1& t1,const T2& t2,const T3& t3) {
|
nuclear@0
|
239 tuple <T0,T1,T2,T3> t;
|
nuclear@0
|
240 t.template get<0>() = t0;
|
nuclear@0
|
241 t.template get<1>() = t1;
|
nuclear@0
|
242 t.template get<2>() = t2;
|
nuclear@0
|
243 t.template get<3>() = t3;
|
nuclear@0
|
244 return t;
|
nuclear@0
|
245 }
|
nuclear@0
|
246
|
nuclear@0
|
247 // Constructs a tuple with 3 elements
|
nuclear@0
|
248 template <typename T0,typename T1,typename T2>
|
nuclear@0
|
249 inline tuple <T0,T1,T2> make_tuple (const T0& t0,
|
nuclear@0
|
250 const T1& t1,const T2& t2) {
|
nuclear@0
|
251 tuple <T0,T1,T2> t;
|
nuclear@0
|
252 t.template get<0>() = t0;
|
nuclear@0
|
253 t.template get<1>() = t1;
|
nuclear@0
|
254 t.template get<2>() = t2;
|
nuclear@0
|
255 return t;
|
nuclear@0
|
256 }
|
nuclear@0
|
257
|
nuclear@0
|
258 // Constructs a tuple with 2 elements
|
nuclear@0
|
259 template <typename T0,typename T1>
|
nuclear@0
|
260 inline tuple <T0,T1> make_tuple (const T0& t0,
|
nuclear@0
|
261 const T1& t1) {
|
nuclear@0
|
262 tuple <T0,T1> t;
|
nuclear@0
|
263 t.template get<0>() = t0;
|
nuclear@0
|
264 t.template get<1>() = t1;
|
nuclear@0
|
265 return t;
|
nuclear@0
|
266 }
|
nuclear@0
|
267
|
nuclear@0
|
268 // Constructs a tuple with 1 elements (well ...)
|
nuclear@0
|
269 template <typename T0>
|
nuclear@0
|
270 inline tuple <T0> make_tuple (const T0& t0) {
|
nuclear@0
|
271 tuple <T0> t;
|
nuclear@0
|
272 t.template get<0>() = t0;
|
nuclear@0
|
273 return t;
|
nuclear@0
|
274 }
|
nuclear@0
|
275
|
nuclear@0
|
276 // Constructs a tuple with 0 elements (well ...)
|
nuclear@0
|
277 inline tuple <> make_tuple () {
|
nuclear@0
|
278 tuple <> t;
|
nuclear@0
|
279 return t;
|
nuclear@0
|
280 }
|
nuclear@0
|
281 };
|
nuclear@0
|
282
|
nuclear@0
|
283 #endif // !! BOOST_TUPLE_INCLUDED
|