Proton  1.1.1
Make porting easy from Python to C++11
tuple.hpp
Go to the documentation of this file.
1 #ifndef PROTON_TUPLE_HEADER
2 #define PROTON_TUPLE_HEADER
3 
4 
5 /** @file tuple.hpp
6  * @brief tuple support.
7  * Please include this header instead of <tuple>.
8  */
9 
10 #include <tuple>
11 #include <algorithm>
12 #include <iostream>
13 #include <initializer_list>
14 #include <algorithm>
15 #include <stdexcept>
16 #include <limits>
17 
18 #include <proton/base.hpp>
19 
20 namespace proton{
21 
22 namespace detail{
23 
24 // helper function to print a tuple of any size
25 template<typename T, std::size_t I>
26 struct output_tuple {
27  static void output(std::ostream& s, T&& t)
28  {
29  output_tuple<T, I-1>::output(s,t);
30  s << ", " << std::get<I-1>(t);
31  }
32 };
33 
34 template<typename T>
35 struct output_tuple<T, 1> {
36  static void output(std::ostream& s, T&& t)
37  {
38  s << std::get<0>(t);
39  }
40 };
41 
42 template<typename T>
43 struct output_tuple<T, 0> {
44  static void output(std::ostream& s, T&& t)
45  {
46  }
47 };
48 
49 constexpr long fix_index(long i, long size)
50 {
51  return (i>size)?
52  size
53  :(
54  (i<0)?
55  (i+size < 0 ?
56  0
57  :
58  i+size
59  )
60  :
61  i
62  );
63 }
64 
65 constexpr long sub_index(long i, long size)
66 {
67  return (i>=size)?
68  size-1
69  :(
70  (i<0)?
71  (i+size < 0 ?
72  0
73  :
74  i+size
75  )
76  :
77  i
78  );
79 }
80 
81 constexpr long get_index(long i, long size)
82 {
83  return (i>=size)?
84  -1
85  :(
86  (i<0)?
87  (i+size < 0 ?
88  -1
89  :
90  i+size
91  )
92  :
93  i
94  );
95 }
96 
97 template<long i, typename ...T>
98 struct at_index{
99  static_assert(i>=0, "out of range");
100  const std::tuple<T...>* p;
101  typedef decltype(std::get<i>(*p)) type;
102 };
103 
104 constexpr long fix_size(long begin, long end, long size)
105 {
106  return fix_index(begin,size)>fix_index(end,size)?
107  0
108  :
109  fix_index(end,size)-fix_index(begin,size);
110 }
111 
112 template<typename T, size_t begin, size_t size>
113 struct sub{
114 private:
115  static_assert(begin < std::tuple_size<T>::value, "out of range");
116 
117  std::tuple<typename std::tuple_element<begin, T>::type> *p;
118  typedef typename sub<T, begin+1,
119  (begin+size > std::tuple_size<T>::value ?
120  (std::tuple_size<T>::value-begin-1)
121  : (size-1))
122  >::type next_types;
123  next_types* q;
124 
125 public:
126  typedef decltype(std::tuple_cat(*p,*q)) type;
127 };
128 
129 template<typename T, size_t begin>
130 struct sub<T, begin, 0>{
131  typedef std::tuple<> type;
132 };
133 
134 template<typename T, size_t begin>
135 struct sub<T,begin,1>{
136  static_assert(begin < std::tuple_size<T>::value, "out of range");
137 
138  typedef std::tuple<typename std::tuple_element<begin,T>::type > type;
139 };
140 
141 
142 template<typename ...T>
143 struct len_t<std::tuple<T...> >{
144  static size_t result(const std::tuple<T...>& x)
145  {
146  return sizeof...(T);
147  }
148 };
149 
150 } // ns detail
151 
152 /** @addtogroup tuple
153  * @{
154  */
155 
156 /** like x[index] in python
157  */
158 
159 template<long index, typename ...T>
160 typename detail::at_index<detail::get_index(index,sizeof...(T)),T...>::type
161  at(const std::tuple<T...>& x)
162 {
163  return std::get<detail::get_index(index,sizeof...(T))>(x);
164 }
165 
166 /** get a slice of tuple x[begin:end] in python
167  */
169 typename detail::sub<std::tuple<T...>, detail::fix_index(begin, sizeof...(T)),
170  detail::fix_size(begin,end, sizeof...(T))>::type
171  sub(const std::tuple<T...>& x)
172 {
173  typedef typename detail::sub<std::tuple<T...>, detail::fix_index(begin, sizeof...(T)),
174  detail::fix_size(begin,end, sizeof...(T))>::type ret_t;
175  return ret_t(*reinterpret_cast<const ret_t*>(&std::get<(detail::sub_index(end-1, sizeof...(T)))>(x))); // [FIXME] in g++, the items in a tuple is in reverse order. for other implementation, need fix.
176 }
177 
178 /** general output for tuple.
179  * @param s the output stream
180  * @param x the tuple to be outputed
181  * @return s
182  */
183 template <typename ...T>
184 std::ostream& operator<<(std::ostream& s, const std::tuple<T...>& x)
185 {
186  s << "(";
187  detail::output_tuple<decltype(x), sizeof...(T)>::output(s,x);
188  s << ")";
189  return s;
190 }
191 
192 template <typename ...T>
193 std::wostream& operator<<(std::wostream& s, const std::tuple<T...>& x)
194 {
195  s << L"(";
196  detail::output_tuple<decltype(x), sizeof...(T)>::output(s,x);
197  s << L")";
198  return s;
199 }
200 
201 /** tuple + tuple
202  */
203 template<typename T2, typename ...T1>
204 auto operator+(const std::tuple<T1...>& x, T2&& y) -> decltype(std::tuple_cat(x,y))
205 {
206  return std::tuple_cat(x,y);
207 }
208 
209 template<typename T2, typename ...T1>
210 auto operator+(std::tuple<T1...>&& x, T2&& y) -> decltype(std::tuple_cat(x,y))
211 {
212  return std::tuple_cat(x,y);
213 }
214 
215 /** eq to make_tuple
216  */
217 template<typename ...T>
218 auto _t(T&& ...x) -> decltype(std::make_tuple(x...))
219 {
220  return std::make_tuple(x...);
221 }
222 
223 /** eq to forward_as_tuple
224  */
225 template<typename ...T>
226 auto _f(T&& ...x) -> decltype(std::forward_as_tuple(x...))
227 {
228  return std::forward_as_tuple(x...);
229 }
230 
231 #if 0
232 /* vector_ * n
233  */
234 template<typename T, typename A>
235 vector_<T,A> operator*(const std::vector<T,A>& s, size_t n)
236 {
237  vector_<T,A> r;
238  r.reserve(s.size()*n);
239  for(size_t i=0; i<n; i++)
240  r.extend(s);
241  return r;
242 }
243 
244 /* n * vector_
245  */
246 template<typename T, typename A>
247 vector_<T,A> operator*(size_t n, const std::vector<T,A>& s)
248 {
249  return s*n;
250 }
251 #endif
252 
253 /**
254  * @example tuple.cpp
255  * @}
256  */
257 }
258 
259 #endif // PROTON_TUPLE_HEADER