You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

284 lines
7.8 KiB

  1. // A very small replacement for boost::tuple
  2. // (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net]
  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.template get<N>();
  143. }
  144. // ... and the const version
  145. template <unsigned N>
  146. const typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () const {
  147. return m.template 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 T0b, typename T1b,typename T2b,typename T3b, typename T4b>
  159. operator tuple <T0b,T1b,T2b,T3b,T4b> () const {
  160. tuple <T0b,T1b,T2b,T3b,T4b> s;
  161. s.m = (typename tuple <T0b,T1b,T2b,T3b,T4b>::very_long)m;
  162. return s;
  163. }
  164. };
  165. // Another way to access an element ...
  166. template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
  167. inline typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
  168. tuple<T0,T1,T2,T3,T4>& m) {
  169. return m.template get<N>();
  170. }
  171. // ... and the const version
  172. template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
  173. inline const typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
  174. const tuple<T0,T1,T2,T3,T4>& m) {
  175. return m.template get<N>();
  176. }
  177. // Constructs a tuple with 5 elements
  178. template <typename T0,typename T1,typename T2,typename T3,typename T4>
  179. inline tuple <T0,T1,T2,T3,T4> make_tuple (const T0& t0,
  180. const T1& t1,const T2& t2,const T3& t3,const T4& t4) {
  181. tuple <T0,T1,T2,T3,T4> t;
  182. t.template get<0>() = t0;
  183. t.template get<1>() = t1;
  184. t.template get<2>() = t2;
  185. t.template get<3>() = t3;
  186. t.template get<4>() = t4;
  187. return t;
  188. }
  189. // Constructs a tuple with 4 elements
  190. template <typename T0,typename T1,typename T2,typename T3>
  191. inline tuple <T0,T1,T2,T3> make_tuple (const T0& t0,
  192. const T1& t1,const T2& t2,const T3& t3) {
  193. tuple <T0,T1,T2,T3> t;
  194. t.template get<0>() = t0;
  195. t.template get<1>() = t1;
  196. t.template get<2>() = t2;
  197. t.template get<3>() = t3;
  198. return t;
  199. }
  200. // Constructs a tuple with 3 elements
  201. template <typename T0,typename T1,typename T2>
  202. inline tuple <T0,T1,T2> make_tuple (const T0& t0,
  203. const T1& t1,const T2& t2) {
  204. tuple <T0,T1,T2> t;
  205. t.template get<0>() = t0;
  206. t.template get<1>() = t1;
  207. t.template get<2>() = t2;
  208. return t;
  209. }
  210. // Constructs a tuple with 2 elements
  211. template <typename T0,typename T1>
  212. inline tuple <T0,T1> make_tuple (const T0& t0,
  213. const T1& t1) {
  214. tuple <T0,T1> t;
  215. t.template get<0>() = t0;
  216. t.template get<1>() = t1;
  217. return t;
  218. }
  219. // Constructs a tuple with 1 elements (well ...)
  220. template <typename T0>
  221. inline tuple <T0> make_tuple (const T0& t0) {
  222. tuple <T0> t;
  223. t.template get<0>() = t0;
  224. return t;
  225. }
  226. // Constructs a tuple with 0 elements (well ...)
  227. inline tuple <> make_tuple () {
  228. tuple <> t;
  229. return t;
  230. }
  231. };
  232. #endif // !! BOOST_TUPLE_INCLUDED