We now have a current svn snapshot of libqxt in our contrib dir, and
[quassel.git] / src / contrib / libqxt-2007-10-24 / src / core / qxttuple.h
1 /****************************************************************************
2 **
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
4 **
5 ** This file is part of the QxtCore module of the Qt eXTension library
6 **
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
9 ** IBM.
10 **
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE.
15 **
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
20 **
21 ** <http://libqxt.sourceforge.net>  <foundation@libqxt.org>
22 **
23 ****************************************************************************/
24
25 #ifndef QXTTUPLE_H
26 #define QXTTUPLE_H
27 #include <qxttypelist.h>
28
29 namespace QxtType
30 {
31
32 template<typename TYPELIST, int INDEX, int STEP=0, bool END=(INDEX==STEP), bool ERROR=(TYPELIST::length==0)>
33 struct get
34     {
35         typedef typename get<typename TYPELIST::tail, INDEX, STEP+1>::type type;
36     };
37
38 template<typename TYPELIST, int INDEX, int STEP>
39 struct get<TYPELIST, INDEX, STEP, false, true>
40     {}; // does not define type
41
42 template<typename TYPELIST, int INDEX, int STEP, bool ERROR>
43 struct get<TYPELIST, INDEX, STEP, true, ERROR>
44     {
45         typedef typename TYPELIST::head type;
46     };
47
48 template<typename TYPELIST, bool LONG=false> class QxtTuple;
49 template<typename TYPELIST, int INDEX, bool LONG, bool EXT=(INDEX>8)> struct QxtTupleValue;
50
51 template<typename TYPELIST, int INDEX> struct QxtTupleValue<TYPELIST, INDEX, true, true>
52 {
53     static typename get<TYPELIST, INDEX>::type value(QxtTuple<TYPELIST,true>* t)
54     {
55         return QxtTupleValue<typename TYPELIST::extend, INDEX-9, TYPELIST::extend::extends>::value(&t->extend);
56     }
57
58     static void setValue(QxtTuple<TYPELIST,true>* t, typename get<TYPELIST, INDEX>::type val)
59     {
60         QxtTupleValue<typename TYPELIST::extend, INDEX-9, TYPELIST::extend::extends>::setValue(&t->extend, val);
61     }
62 };
63
64 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 0, LONG, false>
65 {
66     static typename get<TYPELIST, 0>::type value(QxtTuple<TYPELIST,LONG>* t)
67     {
68         return t->t1;
69     }
70     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 0>::type val)
71     {
72         t->t1 = val;
73     }
74 };
75
76 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 1, LONG, false>
77 {
78     static typename get<TYPELIST, 1>::type value(QxtTuple<TYPELIST,LONG>* t)
79     {
80         return t->t2;
81     }
82     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 1>::type val)
83     {
84         t->t2 = val;
85     }
86 };
87
88 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 2, LONG, false>
89 {
90     static typename get<TYPELIST, 2>::type value(QxtTuple<TYPELIST,LONG>* t)
91     {
92         return t->t3;
93     }
94     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 2>::type val)
95     {
96         t->t3 = val;
97     }
98 };
99
100 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 3, LONG, false>
101 {
102     static typename get<TYPELIST, 3>::type value(QxtTuple<TYPELIST,LONG>* t)
103     {
104         return t->t4;
105     }
106     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 3>::type val)
107     {
108         t->t4 = val;
109     }
110 };
111
112 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 4, LONG, false>
113 {
114     static typename get<TYPELIST, 4>::type value(QxtTuple<TYPELIST,LONG>* t)
115     {
116         return t->t5;
117     }
118     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 4>::type val)
119     {
120         t->t5 = val;
121     }
122 };
123
124 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 5, LONG, false>
125 {
126     static typename get<TYPELIST, 5>::type value(QxtTuple<TYPELIST,LONG>* t)
127     {
128         return t->t6;
129     }
130     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 5>::type val)
131     {
132         t->t6 = val;
133     }
134 };
135
136 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 6, LONG, false>
137 {
138     static typename get<TYPELIST, 6>::type value(QxtTuple<TYPELIST,LONG>* t)
139     {
140         return t->t7;
141     }
142     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 6>::type val)
143     {
144         t->t7 = val;
145     }
146 };
147
148 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 7, LONG, false>
149 {
150     static typename get<TYPELIST, 7>::type value(QxtTuple<TYPELIST,LONG>* t)
151     {
152         return t->t8;
153     }
154     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 7>::type val)
155     {
156         t->t8 = val;
157     }
158 };
159
160 template<typename TYPELIST, bool LONG> struct QxtTupleValue<TYPELIST, 8, LONG, false>
161 {
162     static typename get<TYPELIST, 8>::type value(QxtTuple<TYPELIST,LONG>* t)
163     {
164         return t->t9;
165     }
166     static void setValue(QxtTuple<TYPELIST,LONG>* t, typename get<TYPELIST, 8>::type val)
167     {
168         t->t9 = val;
169     }
170 };
171
172 //-----------------------------------------------------------------------------------------------
173
174 template<typename TYPELIST>
175 /**
176 \class QxtTuple QxtTuple
177
178 \ingroup QxtCore
179
180 \brief Arbitrary-length templated list
181
182 Tuples and cons pairs are both pretty common template metaprogramming hacks. This set of classes
183 attempts to implement a healthy balance between the two. Tuples generally are implemented with a
184 fixed length; cons pairs have a lot of overhead and require a ton of typing. As with all template
185 metaprograms, it may take a while to compile.
186
187 It is recommended to use the convenience macros to create tuples, but you can construct the
188 QxtTypeList template yourself if you desire; this may be preferable if you want to write generic
189 functions that use tuples.
190
191 ----- example:
192 \code
193 #include <QxtTuple.h>
194 #include <iostream>
195 using namespace std;
196
197 int main(int argc, char** argv) {
198     Qxt7Tuple(bool, char, short, int, long long, float, double) tuple;
199
200     tuple.setValue<0>(true);
201     tuple.setValue<1>('a');
202     tuple.setValue<2>(32767);
203     tuple.setValue<3>(1234567);
204     tuple.setValue<4>(987654321);
205     tuple.setValue<5>(1.414);
206     tuple.setValue<6>(3.14159265);
207
208     cout << 0 << "=" << tuple.value<0>() << endl;
209     cout << 1 << "=" << tuple.value<1>() << endl;
210     cout << 2 << "=" << tuple.value<2>() << endl;
211     cout << 3 << "=" << tuple.value<3>() << endl;
212     cout << 4 << "=" << tuple.value<4>() << endl;
213     cout << 5 << "=" << tuple.value<5>() << endl;
214     cout << 6 << "=" << tuple.value<6>() << endl;
215 }
216 \endcode
217 */
218
219 class QxtTuple<TYPELIST,false>
220 {
221 public:
222     template<int INDEX> typename get<TYPELIST, INDEX>::type value()
223     {
224         return QxtTupleValue<TYPELIST, INDEX, false>::value(this);
225     }
226     template<int INDEX> void setValue(typename get<TYPELIST, INDEX>::type val)
227     {
228         QxtTupleValue<TYPELIST, INDEX, false>::setValue(this, val);
229     }
230     bool operator<(const QxtTuple<TYPELIST,false>& other)
231     {
232         if (t1 < other.t1) return true;
233         if (t2 < other.t2) return true;
234         if (t3 < other.t3) return true;
235         if (t4 < other.t4) return true;
236         if (t5 < other.t5) return true;
237         if (t6 < other.t6) return true;
238         if (t7 < other.t7) return true;
239         if (t8 < other.t8) return true;
240         if (t9 < other.t9) return true;
241         return false;
242     }
243     bool operator==(const QxtTuple<TYPELIST,false>& other)
244     {
245         if (t1 != other.t1) return false;
246         if (t2 != other.t2) return false;
247         if (t3 != other.t3) return false;
248         if (t4 != other.t4) return false;
249         if (t5 != other.t5) return false;
250         if (t6 != other.t6) return false;
251         if (t7 != other.t7) return false;
252         if (t8 != other.t8) return false;
253         if (t9 != other.t9) return false;
254         return true;
255     }
256     bool operator>=(const QxtTuple<TYPELIST,false>& other)
257     {
258         return !(*this < other);
259     }
260     bool operator<=(const QxtTuple<TYPELIST,false>& other)
261     {
262         if (t1 <= other.t1) return true;
263         if (t2 <= other.t2) return true;
264         if (t3 <= other.t3) return true;
265         if (t4 <= other.t4) return true;
266         if (t5 <= other.t5) return true;
267         if (t6 <= other.t6) return true;
268         if (t7 <= other.t7) return true;
269         if (t8 <= other.t8) return true;
270         if (t9 <= other.t9) return true;
271         return false;
272     }
273     bool operator>(const QxtTuple<TYPELIST,false>& other)
274     {
275         return !(*this <= other);
276     }
277     bool operator!=(const QxtTuple<TYPELIST,false>& other)
278     {
279         return !(*this == other);
280     }
281
282
283 // if only we could get away with making these protected
284     typename get<TYPELIST, 0>::type t1;
285     typename get<TYPELIST, 1>::type t2;
286     typename get<TYPELIST, 2>::type t3;
287     typename get<TYPELIST, 3>::type t4;
288     typename get<TYPELIST, 4>::type t5;
289     typename get<TYPELIST, 5>::type t6;
290     typename get<TYPELIST, 6>::type t7;
291     typename get<TYPELIST, 7>::type t8;
292     typename get<TYPELIST, 8>::type t9;
293 };
294
295 //-----------------------------------------------------------------------------------------------
296
297 template<typename TYPELIST>
298 class QxtTuple<TYPELIST,true>
299 {
300 public:
301     template<int INDEX> typename get<TYPELIST, INDEX>::type value()
302     {
303         return QxtTupleValue<TYPELIST, INDEX, true>::value(this);
304     }
305     template<int INDEX> void setValue(typename get<TYPELIST, INDEX>::type val)
306     {
307         QxtTupleValue<TYPELIST, INDEX, true>::setValue(this, val);
308     }
309     bool operator<(const QxtTuple<TYPELIST,true>& other)
310     {
311         if (t1 < other.t1) return true;
312         if (t2 < other.t2) return true;
313         if (t3 < other.t3) return true;
314         if (t4 < other.t4) return true;
315         if (t5 < other.t5) return true;
316         if (t6 < other.t6) return true;
317         if (t7 < other.t7) return true;
318         if (t8 < other.t8) return true;
319         if (t9 < other.t9) return true;
320         if (extend < other.extend) return true;
321         return false;
322     }
323     bool operator==(const QxtTuple<TYPELIST,true>& other)
324     {
325         if (t1 != other.t1) return false;
326         if (t2 != other.t2) return false;
327         if (t3 != other.t3) return false;
328         if (t4 != other.t4) return false;
329         if (t5 != other.t5) return false;
330         if (t6 != other.t6) return false;
331         if (t7 != other.t7) return false;
332         if (t8 != other.t8) return false;
333         if (t9 != other.t9) return false;
334         if (extend != other.extend) return false;
335         return true;
336     }
337     bool operator>=(const QxtTuple<TYPELIST,true>& other)
338     {
339         return !(*this < other);
340     }
341     bool operator<=(const QxtTuple<TYPELIST,true>& other)
342     {
343         if (t1 <= other.t1) return true;
344         if (t2 <= other.t2) return true;
345         if (t3 <= other.t3) return true;
346         if (t4 <= other.t4) return true;
347         if (t5 <= other.t5) return true;
348         if (t6 <= other.t6) return true;
349         if (t7 <= other.t7) return true;
350         if (t8 <= other.t8) return true;
351         if (t9 <= other.t9) return true;
352         if (extend <= other.extend) return true;
353         return false;
354     }
355     bool operator>(const QxtTuple<TYPELIST,true>& other)
356     {
357         return !(*this <= other);
358     }
359     bool operator!=(const QxtTuple<TYPELIST,true>& other)
360     {
361         return !(*this == other);
362     }
363
364 // if only we could get away with making these protected
365     typename get<TYPELIST, 0>::type t1;
366     typename get<TYPELIST, 1>::type t2;
367     typename get<TYPELIST, 2>::type t3;
368     typename get<TYPELIST, 3>::type t4;
369     typename get<TYPELIST, 4>::type t5;
370     typename get<TYPELIST, 5>::type t6;
371     typename get<TYPELIST, 6>::type t7;
372     typename get<TYPELIST, 7>::type t8;
373     typename get<TYPELIST, 8>::type t9;
374     QxtTuple<typename TYPELIST::extend> extend;
375 };
376
377 }
378
379 #ifndef QXT_NO_USING
380 using QxtType::QxtTuple;
381 #endif
382
383 #ifndef QXT_NO_MACROS
384 /*! \relates QxtTuple
385  * Declares a one-column tuple.
386  */
387 #define Qxt1Tuple(a) QxtTuple<QxtTypeList<a > >
388
389 /*! \relates QxtTuple
390  * Declares a two-column tuple, similar to QPair.
391  */
392 #define Qxt2Tuple(a, b) QxtTuple<QxtTypeList<a, b > >
393
394 /*! \relates QxtTuple
395  * Declares a three-column tuple, similar to QxtTriple.
396  */
397 #define Qxt3Tuple(a, b, c) QxtTuple<QxtTypeList<a, b, c > >
398
399 /*! \relates QxtTuple
400  * Declares a four-column tuple.
401  */
402 #define Qxt4Tuple(a, b, c, d) QxtTuple<QxtTypeList<a, b, c, d > >
403
404 /*! \relates QxtTuple
405  * Declares a five-column tuple.
406  */
407 #define Qxt5Tuple(a, b, c, d, e) QxtTuple<QxtTypeList<a, b, c, d, e > >
408
409 /*! \relates QxtTuple
410  * Declares a six-column tuple.
411  */
412 #define Qxt6Tuple(a, b, c, d, e, f) QxtTuple<QxtTypeList<a, b, c, d, e, f > >
413
414 /*! \relates QxtTuple
415  * Declares a seven-column tuple.
416  */
417 #define Qxt7Tuple(a, b, c, d, e, f, g) QxtTuple<QxtTypeList<a, b, c, d, e, f, g > >
418
419 /*! \relates QxtTuple
420  * Declares an eight-column tuple.
421  */
422 #define Qxt8Tuple(a, b, c, d, e, f, g, h) QxtTuple<QxtTypeList<a, b, c, d, e, f, g, h > >
423
424 /*! \relates QxtTuple
425  * Declares a nine-column tuple.
426  */
427 #define Qxt9Tuple(a, b, c, d, e, f, g, h, i) QxtTuple<QxtTypeList<a, b, c, d, e, f, g, h, i > >
428
429 /*! \relates QxtTuple
430  * Declares an extended tuple with ten or more columns. Pay special attention to the syntax of the tenth parameter, which
431  * must be a QxtTypeList, not a storage type.
432 \code
433 QxtLongTuple(int, int, int, int, int, int, int, int, int, Qxt1TypeList(int)) tuple; // correct way to implement a 10-tuple
434 QxtLongTuple(int, int, int, int, int, int, int, int, int, int) tuple;              // this will produce a (very long) compile-time error
435 \endcode
436  */
437 #define QxtLongTuple(a, b, c, d, e, f, g, h, i, extend) QxtTuple<QxtTypeList<a, b, c, d, e, f, g, h, i, extend >, true >
438
439 #endif
440
441 #endif