TooN Algorithm Library - tag  0.2
tuple.h
Go to the documentation of this file.
1 #ifndef TAG_TUPLE_H
2 #define TAG_TUPLE_H
3 
4 namespace tag
5 {
7  //
8  // Typesafe, varadic arguments are provided by a typelist
9  //
10 
11  #ifndef DOXYGEN_IGNORE_INTERNAL
12  namespace Internal
13  {
14  struct null{};
15 
16  static null nv;
17 
18  //Index the list, retrieving the value and the type
19  //with a good optimizer, this should be constant time at run-time.
20  template<template<class,class> class List, class C, class D, int i> struct index_l
21  {
22  typedef typename index_l<List, typename D::val_type, typename D::next_type, i-1>::val_type val_type;
23 
24  static const val_type& value(const List<C,D>& l)
25  {
26  return index_l<List, typename D::val_type, typename D::next_type, i-1>::value(l.next);
27  }
28  };
29 
30  template<template<class,class> class List, class C, class D> struct index_l<List, C,D,0>
31  {
32  typedef C val_type;
33  static const val_type& value(const List<C,D>& l)
34  {
35  return l.val;
36  }
37  };
38 
39  //Compute the length of a list
40  template<class C, class D> struct length
41  {
42  enum
43  {
44  len = length<typename D::val_type, typename D::next_type>::len + 1
45  };
46  };
47 
48  template<> struct length<null, null>
49  {
50  enum
51  {
52  len = 0
53  };
54  };
55 
56 
57  template<template<class,class> class List, class C, class D, int i> struct T_index_forward
58  {
59  enum
60  {
61  len = length<C,D>::len
62  };
63 
64  typedef typename index_l<List, C,D,len-i-1>::val_type val_type;
65 
66  static const val_type& value(const List<C,D>& l)
67  {
68  return index_l<List, C, D, len-i-1>::value(l);
69  }
70  };
71  }
72  #endif
73 
74 
208  template<class C, class D> struct T_list
209  {
211  const C& val;
213  typedef C val_type;
214 
216  const D& next;
218  typedef D next_type;
219 
220 
224  T_list(const C& c, const D& d)
225  :val(c),next(d){}
226 
240  template<class X> T_list<X, T_list<C, D> > operator,(const X& c) const
241  {
242  return T_list<X, T_list<C, D> >(c, *this);
243  }
244 
247  template<int i> const typename Internal::T_index_forward<tag::T_list, C,D,i>::val_type& index() const
248  {
249  return Internal::T_index_forward<tag::T_list, C,D,i>::value(*this);
250  }
251 
254  template<int i> class index_type
255  {
256  typedef typename Internal::T_index_forward<tag::T_list, C,D,i>::val_type type;
257  };
258 
259  enum
260  {
262  elements = (Internal::length<C,D>::len)
263  };
264 
265  };
266 
267 
274  template<class C, class D> struct V_list
275  {
276  #ifndef DOXYGEN_IGNORE_INTERNAL
277  C val;
278  typedef C val_type;
279 
280  D next;
281  typedef D next_type;
282 
283 
284  V_list(const C& c, const D& d)
285  :val(c),next(d){}
286 
287  template<class X> V_list<X, V_list<C, D> > operator,(const X& c)
288  {
289  return V_list<X, V_list<C, D> >(c, *this);
290  }
291 
292  template<int i> const typename Internal::T_index_forward<tag::V_list, C,D,i>::val_type& index() const
293  {
294  return Internal::T_index_forward<tag::V_list, C,D,i>::value(*this);
295  }
296 
297  template<int i> class index_type
298  {
299  typedef typename Internal::T_index_forward<tag::V_list, C,D,i>::val_type type;
300  };
301 
302  enum
303  {
305  elements = (Internal::length<C,D>::len)
306  };
307 
308  #endif
309  };
310 
311 
312  #ifndef DOXYGEN_IGNORE_INTERNAL
313  //This class converts a typelist in to an equivalent V_list
314  //This allows R_list to figure out the T_list it should allow
315  //assignment from.
316  namespace Internal
317  {
318  template<class X, class Y> struct r2v
319  {
321  };
322 
323  template<> struct r2v<Internal::null, Internal::null>
324  {
325  typedef V_list<null, null> v;
326  };
327  }
328  #endif
329 
330  #ifndef DOXYGEN_IGNORE_INTERNAL
331  template<class C, class D> struct R_list
332  {
333  private:
334  typedef typename Internal::r2v<C,D>::v equivalent_V_list;
335  R_list(const R_list& );
336  void operator=(const R_list&);
337 
338 
339  public:
340  C& val;
341  typedef C val_type;
342 
343  D& next;
344  typedef D next_type;
345 
346  R_list(C& c, D& d)
347  :val(c),next(d){}
348 
349  template<class X> R_list<X, R_list<C, D> > operator,(X& c)
350  {
351  return R_list<X, R_list<C, D> >(c, *this);
352  }
353 
354  template<int i> const typename Internal::T_index_forward<tag::R_list, C,D,i>::val_type& index() const
355  {
356  return Internal::T_index_forward<tag::R_list, C,D,i>::value(*this);
357  }
358 
359  template<int i> class index_type
360  {
361  typedef typename Internal::T_index_forward<tag::R_list, C,D,i>::val_type type;
362  };
363 
364  enum
365  {
367  elements = (Internal::length<C,D>::len)
368  };
369 
370 
371  template<class X, class Y> friend struct R_list;
372  void operator=(const equivalent_V_list& vlist)
373  {
374  val = vlist.val;
375  next = vlist.next;
376  }
377  };
378  #endif
379 
380  #ifndef DOXYGEN_IGNORE_INTERNAL
381  typedef R_list<Internal::null,Internal::null> R_ListEnd;
382  typedef V_list<Internal::null,Internal::null> V_ListEnd;
383 
384 
385  static R_ListEnd R_TupleHead(Internal::nv, Internal::nv);
386  static V_ListEnd V_TupleHead(Internal::nv, Internal::nv);
387  template<class A, class B, class C=Internal::null, class D=Internal::null, class E=Internal::null, class F=Internal::null, class G=Internal::null, class H=Internal::null, class I=Internal::null, class J=Internal::null> struct V_tuple
388  {
390  };
391 
392  template<class A, class B, class C, class D, class E, class F, class G, class H, class I> struct V_tuple<A,B,C,D,E,F,G,H,I,Internal::null>
393  {
395  };
396 
397  template<class A, class B, class C, class D, class E, class F, class G, class H> struct V_tuple<A,B,C,D,E,F,G,H,Internal::null,Internal::null>
398  {
400  };
401 
402  template<class A, class B, class C, class D, class E, class F, class G> struct V_tuple<A,B,C,D,E,F,G,Internal::null,Internal::null,Internal::null>
403  {
405  };
406 
407  template<class A, class B, class C, class D, class E, class F> struct V_tuple<A,B,C,D,E,F,Internal::null,Internal::null,Internal::null,Internal::null>
408  {
410  };
411 
412  template<class A, class B, class C, class D, class E> struct V_tuple<A,B,C,D,E,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null>
413  {
415  };
416 
417  template<class A, class B, class C, class D> struct V_tuple<A,B,C,D,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null>
418  {
420  };
421 
422  template<class A, class B, class C> struct V_tuple<A,B,C,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null>
423  {
425  };
426 
427  template<class A, class B> struct V_tuple<A,B,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null,Internal::null>
428  {
429  typedef V_list<B, V_list<A, V_ListEnd> > type;
430  };
431  #else
432 
433 
434 
435 
436  template<class A, class B, class C, ...> struct V_tuple
437  {
440  };
441  #endif
442 
443 
444 
445 
446 
452  static const T_ListEnd TupleHead=T_ListEnd(Internal::null(), Internal::null());
453 }
454 
457 #define make_tuple(...) ((tag::TupleHead, ## __VA_ARGS__))
458 
459 
462 #define make_vtuple(...) ((tag::V_TupleHead, ## __VA_ARGS__))
463 
466 #define make_rtuple(...) ((tag::R_TupleHead, ## __VA_ARGS__))
467 
468 
469 #endif
470 
471