Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
tuple.hh
Go to the documentation of this file.
1 #ifndef VCSN_MISC_TUPLE_HH
2 # define VCSN_MISC_TUPLE_HH
3 
4 # include <iostream>
5 # include <tuple>
6 
7 # include <vcsn/misc/hash.hh>
8 
9 namespace vcsn
10 {
11 
12  // These definitions come in handy every time we define variadic tuples.
13  namespace detail
14  {
15 
16  /*-----------------.
17  | index_sequence. |
18  `-----------------*/
19 
20  // See "Pretty-print std::tuple"
21  // <http://stackoverflow.com/questions/6245735>.
22 
23  // See O(log N) implementation of integer sequence
24  // <http://stackoverflow.com/questions/17424477>
25 
26  template<std::size_t...> struct index_sequence
27  { using type = index_sequence; };
28 
29  template<class S1, class S2> struct concat;
30 
31  template<std::size_t... I1, std::size_t... I2>
32  struct concat<index_sequence<I1...>, index_sequence<I2...>>
33  : index_sequence<I1..., (sizeof...(I1)+I2)...>{};
34 
35  template<class S1, class S2>
36  using Concat = typename concat<S1, S2>::type;
37 
38  template<std::size_t N> struct make_index_sequence;
39  template<std::size_t N> using GenSeq =
41 
42  template<std::size_t N>
43  struct make_index_sequence : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{};
44 
45  template<> struct make_index_sequence<0> : index_sequence<>{};
46  template<> struct make_index_sequence<1> : index_sequence<0>{};
47 
48  template<std::size_t off, class S2> struct int_range;
49 
50  template<std::size_t off, std::size_t... I>
51  struct int_range<off, index_sequence<I...>>
52  : index_sequence<I + off...>{};
53 
54  template<std::size_t S, std::size_t L>
56  : int_range<S, typename make_index_sequence<L>::type>{};
57 
58  template<std::size_t S>
59  struct make_index_range<S, 0> : index_sequence<>{};
60  template<std::size_t S>
61  struct make_index_range<S, -1U> : index_sequence<>{};
62 
63  template<typename S1, typename S2>
65 
66  template<std::size_t... I1, std::size_t... I2>
68  : index_sequence<I1..., I2...>{};
69 
70  template <typename S1, typename S2>
72 
73  // There is a bug in clang making this one useless...
74  // The index sequence generated is always <0>
75  // Bug report:
76  // http://llvm.org/bugs/show_bug.cgi?id=14858
77  //template<class... T>
78  //using index_sequence_for = make_index_sequence<sizeof...(T)>;
79 
80 
81  template <typename Fun, typename... Ts>
82  inline void
83  for_(const std::tuple<Ts...>& ts, Fun f)
84  {
85  for_(f, ts, make_index_sequence<sizeof...(Ts)>());
86  }
87 
88  template <typename Fun, typename... Ts, size_t... I>
89  inline void
90  for_(Fun f,
91  const std::tuple<Ts...>& ts,
93  {
94  using swallow = int[];
95  (void) swallow{ (f(std::get<I>(ts)), 0)... };
96  }
97 
99  template <typename Fun, typename... Ts>
100  inline auto
101  map(const std::tuple<Ts...>& ts, Fun f)
102  -> decltype(map_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>()))
103  {
104  return map_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>());
105  }
106 
107  template <typename Fun, typename... Ts, size_t... I>
108  inline auto
109  map_tuple_(Fun f,
110  const std::tuple<Ts...>& ts,
112  -> decltype(map_variadic_(f, std::get<I>(ts)...))
113  {
114  return map_variadic_(f, std::get<I>(ts)...);
115  }
116 
117  template<typename Fun>
118  inline auto
120  -> decltype(std::make_tuple())
121  {
122  return std::make_tuple();
123  }
124 
125  template <typename Fun, typename T, typename... Ts>
126  inline auto
127  map_variadic_(Fun f, T t, Ts&&... ts)
128  -> decltype(std::tuple_cat(std::make_tuple(f(t)), map_variadic_(f, ts...)))
129  {
130  // Enforce evaluation order from left to right.
131  auto r = f(t);
132  return std::tuple_cat(std::make_tuple(r), map_variadic_(f, ts...));
133  }
134 
135 
136 
137 #if 0
138 
139  /*-----------------.
140  | make_gcc_tuple. |
141  `-----------------*/
142 
143  // This does not work, I don't understand why. If you know, please
144  // let me (AD) know.
145  inline auto
147  -> std::tuple<>
148  {
149  return {};
150  }
151 
152  template <typename T, typename... Ts>
153  inline auto
154  make_gcc_tuple(T t, Ts&&... ts)
155  -> decltype(std::tuple_cat(make_gcc_tuple(std::forward<Ts>(ts)...), std::make_tuple(t)));
156 
157  template <typename T, typename... Ts>
158  inline auto
159  make_gcc_tuple(T t, Ts&&... ts)
160  -> decltype(std::tuple_cat(make_gcc_tuple(std::forward<Ts>(ts)...), std::make_tuple(t)))
161  {
162  return std::tuple_cat(make_gcc_tuple(std::forward<Ts>(ts)...), std::make_tuple(t));
163  }
164 
165 #endif
166 
167 
168  /*----------------.
169  | reverse_tuple. |
170  `----------------*/
171 
172  template <typename... Ts>
173  inline auto
174  reverse_tuple(const std::tuple<Ts...>& t)
175  -> decltype(reverse_tuple(t, make_index_sequence<sizeof...(Ts)>()))
176  {
177  return reverse_tuple(t, make_index_sequence<sizeof...(Ts)>());
178  }
179 
180  template <typename... Ts, std::size_t... I>
181  inline auto
182  reverse_tuple(const std::tuple<Ts...>& t, index_sequence<I...>)
183  -> decltype(std::make_tuple(std::get<sizeof...(Ts) - 1 - I>(t)...))
184  {
185  return std::make_tuple(std::get<sizeof...(Ts) - 1 - I>(t)...);
186  }
187 
190 # if VCSN_HAVE_CORRECT_LIST_INITIALIZER_ORDER
191  template <typename... Ts>
192  inline auto
193  make_gcc_tuple(Ts&&... ts)
194  -> decltype(std::make_tuple(std::forward<Ts>(ts)...))
195  {
196  return std::make_tuple(std::forward<Ts>(ts)...);
197  }
198 # else
199  template <typename... Ts>
200  inline auto
201  make_gcc_tuple(Ts&&... ts)
202  -> decltype(reverse_tuple(std::make_tuple(std::forward<Ts>(ts)...)))
203  {
204  return reverse_tuple(std::make_tuple(std::forward<Ts>(ts)...));
205  }
206 # endif
207 
208 
209  /*------------------------.
210  | print(tuple, ostream). |
211  `------------------------*/
212 
213  template<class Tuple, std::size_t N>
215  {
216  static void print(const Tuple& t, std::ostream& o)
217  {
219  o << ", " << std::get<N-1>(t);
220  }
221  };
222 
223  template<class Tuple>
224  struct tuple_printer<Tuple, 1>
225  {
226  static void print(const Tuple& t, std::ostream& o)
227  {
228  o << std::get<0>(t);
229  }
230  };
231 
232  template <typename... Args>
233  std::ostream& print(const std::tuple<Args...>& args, std::ostream& o)
234  {
235  o << '(';
236  tuple_printer<decltype(args), sizeof...(Args)>::print(args, o);
237  return o << ')';
238  }
239 
240 
241  // Compile-time logic
242  // See:
243  // http://stillmoreperfect.blogspot.fr/2010/03/template-metaprogramming-compile-time.html
244 
245  // Test if (c) then T1 else T2
246  template<bool c, class T1, class T2>
247  struct if_c { typedef T1 type; };
248 
249  template<class T1, class T2>
250  struct if_c<false, T1, T2> { typedef T2 type; };
251 
252  template<class C, class T1, class T2>
253  struct if_ : if_c<C::value, T1, T2> {};
254 
255  // Test if (c) then F1 else F2 and get the value
256  template<bool c, class F1, class F2>
257  struct eval_if_c : if_c<c, F1, F2>::type {};
258 
259  template<class C, class F1, class F2>
260  struct eval_if : if_<C, F1, F2>::type {};
261 
262  // And condition on several classes
263  template<class... F>
264  struct and_;
265 
266  template<class F1, class... F>
267  struct and_<F1, F...> : eval_if<F1, and_<F...>, std::false_type>::type {};
268 
269  template<class F1>
270  struct and_<F1> : eval_if<F1, std::true_type, std::false_type>::type {};
271 
272  template<>
273  struct and_<> : std::true_type::type {};
274 
275  // Or condition on several classes
276  template<class... F>
277  struct or_;
278 
279  template<class F1, class... F>
280  struct or_<F1, F...> : eval_if<F1, std::true_type, or_<F...>>::type { };
281 
282  template<class F1>
283  struct or_<F1> : eval_if<F1, std::true_type, std::false_type>::type { };
284 
285  template<>
286  struct or_<> : std::true_type::type {};
287  }
288 
290  template<bool... B>
291  constexpr bool any_()
292  {
294  }
295 
296  // Static evaluation of the 'and' of the template parameters
297  template<bool... B>
298  constexpr bool all_()
299  {
301  }
302 
303 
304 }
305 
306 namespace std
307 {
308 
309  /*-------------------------.
310  | std::hash(tuple<T...>). |
311  `-------------------------*/
312 
313  template <typename... Elements>
314  struct hash<std::tuple<Elements...>>
315  {
316  using value_t = std::tuple<Elements...>;
317  using indices_t = vcsn::detail::make_index_sequence<sizeof...(Elements)>;
318 
319  std::size_t operator()(const value_t& v) const
320  {
321  return hash_(v, indices_t{});
322  }
323 
324  private:
325  template <std::size_t... I>
326  static std::size_t
328  {
329  std::size_t res = 0;
330  using swallow = int[];
331  (void) swallow
332  {
333  (std::hash_combine(res, std::get<I>(v)), 0)...
334  };
335  return res;
336  }
337  };
338 }
339 
340 #endif // !VCSN_MISC_TUPLE_HH
typename concat_index_sequence< S1, S2 >::type concat_sequence
Definition: tuple.hh:71
std::tuple< Elements...> value_t
Definition: tuple.hh:316
std::size_t operator()(const value_t &v) const
Definition: tuple.hh:319
static std::size_t hash_(const value_t &v, vcsn::detail::index_sequence< I...>)
Definition: tuple.hh:327
static void print(const Tuple &t, std::ostream &o)
Definition: tuple.hh:226
auto map_variadic_(Fun) -> decltype(std::make_tuple())
Definition: tuple.hh:119
void for_(const std::tuple< Ts...> &ts, Fun f)
Definition: tuple.hh:83
auto map_tuple_(Fun f, const std::tuple< Ts...> &ts, index_sequence< I...>) -> decltype(map_variadic_(f, std::get< I >(ts)...))
Definition: tuple.hh:109
constexpr bool any_()
Static evaluation of the 'or' of the template parameters.
Definition: tuple.hh:291
auto map(const std::tuple< Ts...> &ts, Fun f) -> decltype(map_tuple_(f, ts, make_index_sequence< sizeof...(Ts)>()))
Map a function on a tuple, return tuple of the results.
Definition: tuple.hh:101
auto reverse_tuple(const std::tuple< Ts...> &t) -> decltype(reverse_tuple(t, make_index_sequence< sizeof...(Ts)>()))
Definition: tuple.hh:174
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:36
typename make_index_sequence< N >::type GenSeq
Definition: tuple.hh:40
static void print(const Tuple &t, std::ostream &o)
Definition: tuple.hh:216
constexpr bool all_()
Definition: tuple.hh:298
std::ostream & print(const std::tuple< Args...> &args, std::ostream &o)
Definition: tuple.hh:233
auto make_gcc_tuple(Ts &&...ts) -> decltype(reverse_tuple(std::make_tuple(std::forward< Ts >(ts)...)))
Same as make_tuple, unless the evaluation of arguments if right-to-left, in which case reverse the re...
Definition: tuple.hh:201