tuple.hpp 8.0 KB

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