Vcsn  2.8
Be Rational
tuple.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <iostream>
4 #include <tuple>
5 
7 #include <vcsn/misc/type_traits.hh> // bool_constant
8 
9 namespace vcsn
10 {
11 
13  template <size_t I, typename T>
15 
16  // These definitions come in handy every time we define variadic tuples.
17  namespace detail
18  {
19 
20  /*-----------------.
21  | index_sequence. |
22  `-----------------*/
23 
24  // See "Pretty-print std::tuple"
25  // <http://stackoverflow.com/questions/6245735>.
26 
27  // See O(log N) implementation of integer sequence
28  // <http://stackoverflow.com/questions/17424477>
29 
31  template <std::size_t...>
33  {
35  };
36 
37  /*-----------------------.
38  | make_index_sequence. |
39  `-----------------------*/
40 
43  template <typename S1, typename S2>
44  struct concat;
45 
46  template <std::size_t... I1, std::size_t... I2>
47  struct concat<index_sequence<I1...>, index_sequence<I2...>>
48  : index_sequence<I1..., (sizeof...(I1)+I2)...>
49  {};
50 
51  template <typename S1, typename S2>
52  using concat_t = typename concat<S1, S2>::type;
53 
55  template <std::size_t N>
57  template <std::size_t N>
59 
60  template <std::size_t N>
61  struct make_index_sequence
62  : concat_t<make_index_sequence_t<N/2>,
63  make_index_sequence_t<N - N/2>>
64  {};
65 
66  template <> struct make_index_sequence<0> : index_sequence<>{};
67  template <> struct make_index_sequence<1> : index_sequence<0>{};
68 
69  template <std::size_t off, typename S2>
70  struct int_range;
71 
72  template <std::size_t off, std::size_t... I>
73  struct int_range<off, index_sequence<I...>>
74  : index_sequence<I + off...>
75  {};
76 
77 
78 
79  /*--------------------.
80  | make_index_range. |
81  `--------------------*/
82 
87  template <std::size_t S, std::size_t L>
89  : int_range<S, make_index_sequence_t<L>>
90  {};
91 
92 
93  template <std::size_t S>
95  template <std::size_t S>
96  struct make_index_range_impl<S, -1U> : index_sequence<>{};
97 
102  template <std::size_t S, std::size_t E>
104  : make_index_range_impl<S, E - S>
105  {};
106 
107  template <std::size_t S, std::size_t E>
109 
110 
111  /*-------------------.
112  | concat_sequence. |
113  `-------------------*/
114 
116  template <typename S1, typename S2>
118 
119  template <std::size_t... I1, std::size_t... I2>
121  : index_sequence<I1..., I2...>{};
122 
123  template <typename S1, typename S2>
125 
126  // There is a bug in clang making this one useless...
127  // The index sequence generated is always <0>
128  // Bug report:
129  // http://llvm.org/bugs/show_bug.cgi?id=14858
130  //template <typename... T>
131  //using index_sequence_for = make_index_sequence<sizeof...(T)>;
132 
133 
134  /*-----------------------.
135  | sequence_difference. |
136  `-----------------------*/
137 
141  template <typename S1, typename S2>
143 
144  template <typename S1, typename S2>
145  using sequence_difference
146  = typename index_sequence_difference<typename S1::type,
147  typename S2::type>::type;
148 
149  template <std::size_t I1_1, std::size_t... I1, std::size_t... I2>
151  index_sequence<I1_1, I2...>>
152  {
153  using type = sequence_difference<index_sequence<I1...>,
154  index_sequence<I2...>>;
155  };
156 
157  template <std::size_t I1_1, std::size_t I2_1,
158  std::size_t... I1, std::size_t... I2>
160  index_sequence<I2_1, I2...>>
161  {
162  using type =
165  index_sequence<I2_1, I2...>>>;
166  };
167 
168  template <std::size_t I1_1, std::size_t... I1>
170  index_sequence<>>
171  {
172  using type =
176  };
177 
178  template <>
180  {
181  using type = typename index_sequence<>::type;
182  };
183 
184 
185  /*--------------------.
186  | punched_sequence. |
187  `--------------------*/
188 
190  template <std::size_t N, std::size_t Gap>
191  using punched_sequence
194 
195 
196  /*--------.
197  | for_. |
198  `--------*/
199 
200 
202  template <typename Fun, typename... Ts>
203  void
204  for_(const std::tuple<Ts...>& ts, Fun f)
205  {
206  for_(f, ts, make_index_sequence<sizeof...(Ts)>());
207  }
208 
209  template <typename Fun, typename... Ts, size_t... I>
210  void
211  for_(Fun f,
212  const std::tuple<Ts...>& ts,
214  {
215  using swallow = int[];
216  (void) swallow{ (f(std::get<I>(ts)), 0)... };
217  }
218 
219 
221  template <typename Fun, typename... Ts>
222  auto
223  map(const std::tuple<Ts...>& ts, Fun f)
224  -> decltype(map_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>()))
225  {
226  return map_impl_(f, ts, make_index_sequence<sizeof...(Ts)>());
227  }
228 
229  template <typename Fun, typename... Ts, size_t... I>
230  auto
231  map_impl_(Fun f,
232  const std::tuple<Ts...>& ts,
234  {
235  return std::make_tuple(f(std::get<I>(ts))...);
236  }
237 
238 
240  template <typename Fun, typename... Args>
241  auto
242  apply(Fun f, const std::tuple<Args...>& args)
243  // Return type needed by G++ 5.
244  -> decltype(apply_impl_(f, args, make_index_sequence<sizeof...(Args)>()))
245  {
246  return apply_impl_(f, args, make_index_sequence<sizeof...(Args)>());
247  }
248 
249  template <typename Fun, typename... Args, size_t... I>
250  auto
251  apply_impl_(Fun f,
252  const std::tuple<Args...>& args,
254  // Return type needed by G++ 5.
255  -> decltype(f(std::get<I>(args)...))
256  {
257  return f(std::get<I>(args)...);
258  }
259 
260 
263  template <typename... Funs, typename... Args>
264  auto
265  apply(const std::tuple<Funs...>& funs, const std::tuple<Args...>& args)
266  {
267  static_assert(sizeof...(Funs) == sizeof...(Args),
268  "tuples of functions and arguments of different sizes");
269  return apply_impl_(funs, args, make_index_sequence<sizeof...(Funs)>());
270  }
271 
274  template <typename... Funs, typename... Args, size_t... I>
275  auto
276  apply_impl_(const std::tuple<Funs...>& funs,
277  const std::tuple<Args...>& args,
279  {
280  return std::make_tuple(std::get<I>(funs)(std::get<I>(args))...);
281  }
282 
283 
286  template <typename Fun, typename... Objs, typename... Args>
287  auto
288  apply(Fun fun,
289  const std::tuple<Objs...>& objs, const std::tuple<Args...>& args)
290  {
291  static_assert(sizeof...(Objs) == sizeof...(Args),
292  "tuples of objects and arguments of different sizes");
293  return apply_impl_(fun, objs, args,
294  make_index_sequence<sizeof...(Objs)>());
295  }
296 
297  template <typename Fun, typename... Objs, typename... Args, size_t... I>
298  auto
299  apply_impl_(Fun fun,
300  const std::tuple<Objs...>& objs,
301  const std::tuple<Args...>& args,
303  {
304  return std::make_tuple(fun(std::get<I>(objs), std::get<I>(args))...);
305  }
306 
307 
308  /*--------------------------------------------.
309  | Variadic Cartesian product of containers. |
310  `--------------------------------------------*/
311 
317  template <typename Fun>
318  void
319  cross(Fun f)
320  {
321  f();
322  }
323 
324  template <typename Fun,
325  typename Cont, typename... Conts>
326  void
327  cross(Fun f,
328  const Cont& head, const Conts&... tails)
329  {
330  for (const typename Cont::value_type& h: head)
331  cross([&](const typename Conts::value_type&... tails)
332  { f(h, tails...); },
333  tails...);
334  }
335 
336  template <typename Fun, typename... Ts, size_t... I>
337  void
339  const std::tuple<Ts...>& ts,
341  {
342  cross(f, std::get<I>(ts)...);
343  }
344 
345  template <typename Fun, typename... Ts>
346  void
347  cross_tuple(Fun f,
348  const std::tuple<Ts...>& ts)
349  {
350  cross_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>());
351  }
352 
353 
354 
355  /*----------------.
356  | reverse_tuple. |
357  `----------------*/
358 
359  template <typename... Ts>
360  auto
361  reverse_tuple(const std::tuple<Ts...>& t)
362  -> decltype(reverse_tuple(t, make_index_sequence<sizeof...(Ts)>()))
363  {
364  return reverse_tuple(t, make_index_sequence<sizeof...(Ts)>());
365  }
366 
367  template <typename... Ts, std::size_t... I>
368  auto
369  reverse_tuple(const std::tuple<Ts...>& t, index_sequence<I...>)
370  -> decltype(std::make_tuple(std::get<sizeof...(Ts) - 1 - I>(t)...))
371  {
372  return std::make_tuple(std::get<sizeof...(Ts) - 1 - I>(t)...);
373  }
374 
377 #if VCSN_HAVE_CORRECT_LIST_INITIALIZER_ORDER
378  template <typename... Ts>
379  auto
380  make_gcc_tuple(Ts&&... ts)
381  -> decltype(std::make_tuple(std::forward<Ts>(ts)...))
382  {
383  return std::make_tuple(std::forward<Ts>(ts)...);
384  }
385 #else
386  template <typename... Ts>
387  auto
388  make_gcc_tuple(Ts&&... ts)
389  -> decltype(reverse_tuple(std::make_tuple(std::forward<Ts>(ts)...)))
390  {
391  return reverse_tuple(std::make_tuple(std::forward<Ts>(ts)...));
392  }
393 #endif
394 
395 
396  /*------------------------.
397  | print(tuple, ostream). |
398  `------------------------*/
399 
400  template <typename Tuple, std::size_t N>
402  {
403  static void print(const Tuple& t, std::ostream& o)
404  {
406  o << ", " << std::get<N-1>(t);
407  }
408  };
409 
410  template <typename Tuple>
411  struct tuple_printer<Tuple, 1>
412  {
413  static void print(const Tuple& t, std::ostream& o)
414  {
415  o << std::get<0>(t);
416  }
417  };
418 
419  template <typename... Args>
420  std::ostream& print(const std::tuple<Args...>& args, std::ostream& o)
421  {
422  o << '(';
423  tuple_printer<decltype(args), sizeof...(Args)>::print(args, o);
424  return o << ')';
425  }
426 
427 
428  // Compile-time logic
429  // See:
430  // http://stillmoreperfect.blogspot.fr/2010/03/template-metaprogramming-compile-time.html
431 
432  // Test if (c) then T1 else T2
433  template <bool c, typename T1, typename T2>
434  struct if_c { typedef T1 type; };
435 
436  template <typename T1, typename T2>
437  struct if_c<false, T1, T2> { typedef T2 type; };
438 
439  template <typename C, typename T1, typename T2>
440  struct if_ : if_c<C::value, T1, T2> {};
441 
443  template <bool c, typename F1, typename F2>
444  struct eval_if_c : if_c<c, F1, F2>::type {};
445 
446  template <typename C, typename F1, typename F2>
447  struct eval_if : if_<C, F1, F2>::type {};
448 
450  template <typename... F>
451  struct and_;
452 
453  template <typename F1, typename... F>
454  struct and_<F1, F...> : eval_if<F1, and_<F...>, std::false_type>::type {};
455 
456  template <typename F1>
457  struct and_<F1> : eval_if<F1, std::true_type, std::false_type>::type {};
458 
459  template <>
460  struct and_<> : std::true_type::type {};
461 
463  template <typename... F>
464  struct or_;
465 
466  template <typename F1, typename... F>
467  struct or_<F1, F...> : eval_if<F1, std::true_type, or_<F...>>::type { };
468 
469  template <typename F1>
470  struct or_<F1> : eval_if<F1, std::true_type, std::false_type>::type { };
471 
472  template <>
473  struct or_<> : std::true_type::type {};
474  }
475 
477  template <bool... B>
478  constexpr bool any_()
479  {
480  return detail::or_<bool_constant<B>...>::value;
481  }
482 
483  // Static evaluation of the 'and' of the template parameters
484  template <bool... B>
485  constexpr bool all_()
486  {
487  return detail::and_<bool_constant<B>...>::value;
488  }
489 
491  template <typename... Bool>
492  bool all(Bool&&... values)
493  {
494  bool res = true;
495  using swallow = int[];
496  (void) swallow
497  {
498  (res = res && values, 0)...
499  };
500  return res;
501  }
502 
506  struct any
507  {
508  template <typename... Bool>
509  bool operator()(Bool&&... values)
510  {
511  bool res = false;
512  using swallow = int[];
513  (void) swallow
514  {
515  (res = res || values, 0)...
516  };
517  return res;
518  }
519  };
520 }
521 
522 namespace std
523 {
524 
525  /*-------------------------.
526  | std::hash(tuple<T...>). |
527  `-------------------------*/
528 
529  template <typename... Elements>
530  struct hash<std::tuple<Elements...>>
531  {
532  using value_t = std::tuple<Elements...>;
533  using indices_t = vcsn::detail::make_index_sequence<sizeof...(Elements)>;
534 
535  std::size_t operator()(const value_t& v) const
536  {
537  return hash_(v, indices_t{});
538  }
539 
540  private:
541  template <std::size_t... I>
542  static std::size_t
544  {
545  std::size_t res = 0;
546  using swallow = int[];
547  (void) swallow
548  {
549  (vcsn::hash_combine(res, std::get<I>(v)), 0)...
550  };
551  return res;
552  }
553  };
554 }
constexpr bool any_()
Static evaluation of the &#39;or&#39; of the template parameters.
Definition: tuple.hh:478
concat_sequence< make_index_range_t< 0, Gap >, make_index_range_t< Gap+1, N > > punched_sequence
An index sequence with a gap.
Definition: tuple.hh:193
auto map_impl_(Fun f, const std::tuple< Ts... > &ts, index_sequence< I... >)
Definition: tuple.hh:231
void cross_tuple_(Fun f, const std::tuple< Ts... > &ts, index_sequence< I... >)
Definition: tuple.hh:338
static std::size_t hash_(const value_t &v, vcsn::detail::index_sequence< I... >)
Definition: tuple.hh:543
A static range.
Definition: tuple.hh:103
auto apply_impl_(Fun f, const std::tuple< Args... > &args, index_sequence< I... >) -> decltype(f(std::get< I >(args)...))
Definition: tuple.hh:251
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
Definition: tuple.hh:347
concat_sequence< index_sequence< I1_1 >, sequence_difference< index_sequence< I1... >, index_sequence< I2_1, I2... > >> type
Definition: tuple.hh:165
concat_sequence< index_sequence< I1_1 >, sequence_difference< index_sequence< I1... >, index_sequence<> >> type
Definition: tuple.hh:175
bool operator()(Bool &&... values)
Definition: tuple.hh:509
typename index_sequence_difference< typename S1::type, typename S2::type >::type sequence_difference
Definition: tuple.hh:147
auto tuple(const Auts &... as)
Build the (accessible part of the) tuple.
And condition on several typenames.
Definition: tuple.hh:451
Concat two sequences of size_t, adding the size of the first.
Definition: tuple.hh:44
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
Definition: tuple.hh:14
constexpr bool all_()
Definition: tuple.hh:485
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:388
Build the static sequence of size_t [0, N[.
Definition: tuple.hh:56
Concatenate two static sequences of size_t.
Definition: tuple.hh:117
Whether some of the values evaluate as true.
Definition: tuple.hh:506
Definition: a-star.hh:8
std::ostream & print(const std::tuple< Args... > &args, std::ostream &o)
Definition: tuple.hh:420
typename make_index_sequence< N >::type make_index_sequence_t
Definition: tuple.hh:58
std::string type(const automaton &a)
The implementation type of a.
Definition: others.cc:238
auto reverse_tuple(const std::tuple< Ts... > &t) -> decltype(reverse_tuple(t, make_index_sequence< sizeof...(Ts)>()))
Definition: tuple.hh:361
sequence_difference< index_sequence< I1... >, index_sequence< I2... > > type
Definition: tuple.hh:154
std::tuple< Elements... > value_t
Definition: tuple.hh:532
auto apply(Fun f, const std::tuple< Args... > &args) -> decltype(apply_impl_(f, args, make_index_sequence< sizeof...(Args)>()))
Unpack a tuple, and pass its content as argument to a funtion.
Definition: tuple.hh:242
typename concat_index_sequence< S1, S2 >::type concat_sequence
Definition: tuple.hh:124
The list containing all the elements of I1 (contiguous sequence from 0 to N) not present in I2 (arbit...
Definition: tuple.hh:142
typename make_index_range< S, E >::type make_index_range_t
Definition: tuple.hh:108
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &... v)
Definition: tuple.hh:73
A static list of size_t.
Definition: tuple.hh:32
std::size_t operator()(const value_t &v) const
Definition: tuple.hh:535
static void print(const Tuple &t, std::ostream &o)
Definition: tuple.hh:403
Or condition on several typenames.
Definition: tuple.hh:464
static void print(const Tuple &t, std::ostream &o)
Definition: tuple.hh:413
void hash_combine(std::size_t &seed, const T &v)
Definition: functional.hh:63
Test if (c) then F1 else F2 and get the value.
Definition: tuple.hh:444
void for_(const std::tuple< Ts... > &ts, Fun f)
Run function f on each member of ts.
Definition: tuple.hh:204
STL namespace.
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:223
void cross(Fun f)
Variadic Cartesian product of containers.
Definition: tuple.hh:319
return res
Definition: multiply.hh:399
bool all(Bool &&... values)
Whether all the values evaluate as true.
Definition: tuple.hh:492