Vcsn  2.3
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 
30  template <std::size_t...> struct index_sequence
31  { using type = index_sequence; };
32 
33  template <typename S1, typename S2> struct concat;
34 
35  template <std::size_t... I1, std::size_t... I2>
36  struct concat<index_sequence<I1...>, index_sequence<I2...>>
37  : index_sequence<I1..., (sizeof...(I1)+I2)...>{};
38 
39  template <typename S1, typename S2>
40  using Concat = typename concat<S1, S2>::type;
41 
42  template <std::size_t N> struct make_index_sequence;
43  template <std::size_t N> using GenSeq =
45 
46  template <std::size_t N>
47  struct make_index_sequence : Concat<GenSeq<N/2>, GenSeq<N - N/2>>{};
48 
49  template <> struct make_index_sequence<0> : index_sequence<>{};
50  template <> struct make_index_sequence<1> : index_sequence<0>{};
51 
52  template <std::size_t off, typename S2> struct int_range;
53 
54  template <std::size_t off, std::size_t... I>
55  struct int_range<off, index_sequence<I...>>
56  : index_sequence<I + off...>{};
57 
58 
59  /*--------------------.
60  | make_index_range. |
61  `--------------------*/
62 
67  template <std::size_t S, std::size_t L>
69  : int_range<S, typename make_index_sequence<L>::type>
70  {};
71 
72 
73  template <std::size_t S>
75  template <std::size_t S>
76  struct make_index_range_impl<S, -1U> : index_sequence<>{};
77 
82  template <std::size_t S, std::size_t E>
84  : make_index_range_impl<S, E - S>
85  {};
86 
87  template <std::size_t S, std::size_t E>
89 
90 
91 
92  template <typename S1, typename S2>
94 
95  template <std::size_t... I1, std::size_t... I2>
97  : index_sequence<I1..., I2...>{};
98 
99  template <typename S1, typename S2>
101 
102  // There is a bug in clang making this one useless...
103  // The index sequence generated is always <0>
104  // Bug report:
105  // http://llvm.org/bugs/show_bug.cgi?id=14858
106  //template <typename... T>
107  //using index_sequence_for = make_index_sequence<sizeof...(T)>;
108 
113  template <typename S1, typename S2>
115 
116  template <std::size_t I1_1, std::size_t... I1, std::size_t... I2>
118  index_sequence<I1_1, I2...>>
119  {
120  using type =
123  };
124 
125  template <std::size_t I1_1, std::size_t I2_1,
126  std::size_t... I1, std::size_t... I2>
128  index_sequence<I2_1, I2...>>
129  {
130  using type =
134  };
135 
136  template <std::size_t I1_1, std::size_t... I1>
138  {
139  using type =
143  };
144 
145  template <>
147  {
148  using type = typename index_sequence<>::type;
149  };
150 
151  template <typename S1, typename S2>
152  using sequence_difference
153  = typename index_sequence_difference<typename S1::type,
154  typename S2::type>::type;
155 
156  template <typename Fun, typename... Ts>
157  void
158  for_(const std::tuple<Ts...>& ts, Fun f)
159  {
160  for_(f, ts, make_index_sequence<sizeof...(Ts)>());
161  }
162 
163  template <typename Fun, typename... Ts, size_t... I>
164  void
165  for_(Fun f,
166  const std::tuple<Ts...>& ts,
168  {
169  using swallow = int[];
170  (void) swallow{ (f(std::get<I>(ts)), 0)... };
171  }
172 
173 
175  template <typename Fun, typename... Ts>
176  auto
177  map(const std::tuple<Ts...>& ts, Fun f)
178  -> decltype(map_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>()))
179  {
180  return map_impl_(f, ts, make_index_sequence<sizeof...(Ts)>());
181  }
182 
183  template <typename Fun, typename... Ts, size_t... I>
184  auto
185  map_impl_(Fun f,
186  const std::tuple<Ts...>& ts,
188  {
189  return std::make_tuple(f(std::get<I>(ts))...);
190  }
191 
192 
194  template <typename Fun, typename... Args>
195  auto
196  apply(Fun f, const std::tuple<Args...>& args)
197  // Return type needed by G++ 5.
198  -> decltype(apply_impl_(f, args, make_index_sequence<sizeof...(Args)>()))
199  {
200  return apply_impl_(f, args, make_index_sequence<sizeof...(Args)>());
201  }
202 
203  template <typename Fun, typename... Args, size_t... I>
204  auto
205  apply_impl_(Fun f,
206  const std::tuple<Args...>& args,
208  // Return type needed by G++ 5.
209  -> decltype(f(std::get<I>(args)...))
210  {
211  return f(std::get<I>(args)...);
212  }
213 
214 
217  template <typename... Funs, typename... Args>
218  auto
219  apply(const std::tuple<Funs...>& funs, const std::tuple<Args...>& args)
220  {
221  static_assert(sizeof...(Funs) == sizeof...(Args),
222  "tuples of functions and arguments of different sizes");
223  return apply_impl_(funs, args, make_index_sequence<sizeof...(Funs)>());
224  }
225 
228  template <typename... Funs, typename... Args, size_t... I>
229  auto
230  apply_impl_(const std::tuple<Funs...>& funs,
231  const std::tuple<Args...>& args,
233  {
234  return std::make_tuple(std::get<I>(funs)(std::get<I>(args))...);
235  }
236 
237 
240  template <typename Fun, typename... Objs, typename... Args>
241  auto
242  apply(Fun fun,
243  const std::tuple<Objs...>& objs, const std::tuple<Args...>& args)
244  {
245  static_assert(sizeof...(Objs) == sizeof...(Args),
246  "tuples of objects and arguments of different sizes");
247  return apply_impl_(fun, objs, args,
248  make_index_sequence<sizeof...(Objs)>());
249  }
250 
251  template <typename Fun, typename... Objs, typename... Args, size_t... I>
252  auto
253  apply_impl_(Fun fun,
254  const std::tuple<Objs...>& objs,
255  const std::tuple<Args...>& args,
257  {
258  return std::make_tuple(fun(std::get<I>(objs), std::get<I>(args))...);
259  }
260 
261 
262  /*--------------------------------------------.
263  | Variadic Cartesian product of containers. |
264  `--------------------------------------------*/
265 
271  template <typename Fun>
272  void
273  cross(Fun f)
274  {
275  f();
276  }
277 
278  template <typename Fun,
279  typename Cont, typename... Conts>
280  void
281  cross(Fun f,
282  const Cont& head, const Conts&... tails)
283  {
284  for (const typename Cont::value_type& h: head)
285  cross([&](const typename Conts::value_type&... tails)
286  { f(h, tails...); },
287  tails...);
288  }
289 
290  template <typename Fun, typename... Ts, size_t... I>
291  void
293  const std::tuple<Ts...>& ts,
295  {
296  cross(f, std::get<I>(ts)...);
297  }
298 
299  template <typename Fun, typename... Ts>
300  void
301  cross_tuple(Fun f,
302  const std::tuple<Ts...>& ts)
303  {
304  cross_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>());
305  }
306 
307 
308 
309  /*----------------.
310  | reverse_tuple. |
311  `----------------*/
312 
313  template <typename... Ts>
314  auto
315  reverse_tuple(const std::tuple<Ts...>& t)
316  -> decltype(reverse_tuple(t, make_index_sequence<sizeof...(Ts)>()))
317  {
318  return reverse_tuple(t, make_index_sequence<sizeof...(Ts)>());
319  }
320 
321  template <typename... Ts, std::size_t... I>
322  auto
323  reverse_tuple(const std::tuple<Ts...>& t, index_sequence<I...>)
324  -> decltype(std::make_tuple(std::get<sizeof...(Ts) - 1 - I>(t)...))
325  {
326  return std::make_tuple(std::get<sizeof...(Ts) - 1 - I>(t)...);
327  }
328 
331 #if VCSN_HAVE_CORRECT_LIST_INITIALIZER_ORDER
332  template <typename... Ts>
333  auto
334  make_gcc_tuple(Ts&&... ts)
335  -> decltype(std::make_tuple(std::forward<Ts>(ts)...))
336  {
337  return std::make_tuple(std::forward<Ts>(ts)...);
338  }
339 #else
340  template <typename... Ts>
341  auto
342  make_gcc_tuple(Ts&&... ts)
343  -> decltype(reverse_tuple(std::make_tuple(std::forward<Ts>(ts)...)))
344  {
345  return reverse_tuple(std::make_tuple(std::forward<Ts>(ts)...));
346  }
347 #endif
348 
349 
350  /*------------------------.
351  | print(tuple, ostream). |
352  `------------------------*/
353 
354  template <typename Tuple, std::size_t N>
356  {
357  static void print(const Tuple& t, std::ostream& o)
358  {
360  o << ", " << std::get<N-1>(t);
361  }
362  };
363 
364  template <typename Tuple>
365  struct tuple_printer<Tuple, 1>
366  {
367  static void print(const Tuple& t, std::ostream& o)
368  {
369  o << std::get<0>(t);
370  }
371  };
372 
373  template <typename... Args>
374  std::ostream& print(const std::tuple<Args...>& args, std::ostream& o)
375  {
376  o << '(';
377  tuple_printer<decltype(args), sizeof...(Args)>::print(args, o);
378  return o << ')';
379  }
380 
381 
382  // Compile-time logic
383  // See:
384  // http://stillmoreperfect.blogspot.fr/2010/03/template-metaprogramming-compile-time.html
385 
386  // Test if (c) then T1 else T2
387  template <bool c, typename T1, typename T2>
388  struct if_c { typedef T1 type; };
389 
390  template <typename T1, typename T2>
391  struct if_c<false, T1, T2> { typedef T2 type; };
392 
393  template <typename C, typename T1, typename T2>
394  struct if_ : if_c<C::value, T1, T2> {};
395 
397  template <bool c, typename F1, typename F2>
398  struct eval_if_c : if_c<c, F1, F2>::type {};
399 
400  template <typename C, typename F1, typename F2>
401  struct eval_if : if_<C, F1, F2>::type {};
402 
404  template <typename... F>
405  struct and_;
406 
407  template <typename F1, typename... F>
408  struct and_<F1, F...> : eval_if<F1, and_<F...>, std::false_type>::type {};
409 
410  template <typename F1>
411  struct and_<F1> : eval_if<F1, std::true_type, std::false_type>::type {};
412 
413  template <>
414  struct and_<> : std::true_type::type {};
415 
417  template <typename... F>
418  struct or_;
419 
420  template <typename F1, typename... F>
421  struct or_<F1, F...> : eval_if<F1, std::true_type, or_<F...>>::type { };
422 
423  template <typename F1>
424  struct or_<F1> : eval_if<F1, std::true_type, std::false_type>::type { };
425 
426  template <>
427  struct or_<> : std::true_type::type {};
428  }
429 
431  template <bool... B>
432  constexpr bool any_()
433  {
434  return detail::or_<bool_constant<B>...>::value;
435  }
436 
437  // Static evaluation of the 'and' of the template parameters
438  template <bool... B>
439  constexpr bool all_()
440  {
441  return detail::and_<bool_constant<B>...>::value;
442  }
443 
445  template <typename... Bool>
446  bool all(Bool&&... values)
447  {
448  bool res = true;
449  using swallow = int[];
450  (void) swallow
451  {
452  (res = res && values, 0)...
453  };
454  return res;
455  }
456 
460  struct any
461  {
462  template <typename... Bool>
463  bool operator()(Bool&&... values)
464  {
465  bool res = false;
466  using swallow = int[];
467  (void) swallow
468  {
469  (res = res || values, 0)...
470  };
471  return res;
472  }
473  };
474 }
475 
476 namespace std
477 {
478 
479  /*-------------------------.
480  | std::hash(tuple<T...>). |
481  `-------------------------*/
482 
483  template <typename... Elements>
484  struct hash<std::tuple<Elements...>>
485  {
486  using value_t = std::tuple<Elements...>;
487  using indices_t = vcsn::detail::make_index_sequence<sizeof...(Elements)>;
488 
489  std::size_t operator()(const value_t& v) const
490  {
491  return hash_(v, indices_t{});
492  }
493 
494  private:
495  template <std::size_t... I>
496  static std::size_t
498  {
499  std::size_t res = 0;
500  using swallow = int[];
501  (void) swallow
502  {
503  (vcsn::hash_combine(res, std::get<I>(v)), 0)...
504  };
505  return res;
506  }
507  };
508 }
typename index_sequence_difference< typename S1::type, typename S2::type >::type sequence_difference
Definition: tuple.hh:154
std::ostream & print(const std::tuple< Args... > &args, std::ostream &o)
Definition: tuple.hh:374
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
Definition: tuple.hh:14
std::string type(const automaton &a)
The implementation type of a.
Definition: others.cc:231
And condition on several typenames.
Definition: tuple.hh:405
STL namespace.
auto map_impl_(Fun f, const std::tuple< Ts... > &ts, index_sequence< I... >)
Definition: tuple.hh:185
static void print(const Tuple &t, std::ostream &o)
Definition: tuple.hh:357
constexpr bool all_()
Definition: tuple.hh:439
void cross(Fun f)
Variadic Cartesian product of containers.
Definition: tuple.hh:273
std::tuple< Elements... > value_t
Definition: tuple.hh:486
static void print(const Tuple &t, std::ostream &o)
Definition: tuple.hh:367
typename concat_index_sequence< index_sequence< I1_1 >, typename index_sequence_difference< index_sequence< I1... >, index_sequence<>>::type >::type type
Definition: tuple.hh:142
A static range.
Definition: tuple.hh:83
return res
Definition: multiply.hh:398
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
Definition: tuple.hh:43
void cross_tuple_(Fun f, const std::tuple< Ts... > &ts, index_sequence< I... >)
Definition: tuple.hh:292
std::size_t operator()(const value_t &v) const
Definition: tuple.hh:489
auto tuple(const Auts &...as)
Build the (accessible part of the) tuple.
constexpr bool any_()
Static evaluation of the 'or' of the template parameters.
Definition: tuple.hh:432
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:196
Or condition on several typenames.
Definition: tuple.hh:418
Definition: a-star.hh:8
typename index_sequence_difference< index_sequence< I1... >, index_sequence< I2... >>::type type
Definition: tuple.hh:122
typename make_index_sequence< N >::type GenSeq
Definition: tuple.hh:44
typename concat_index_sequence< index_sequence< I1_1 >, typename index_sequence_difference< index_sequence< I1... >, index_sequence< I2_1, I2... >>::type >::type type
Definition: tuple.hh:133
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:177
Get the list containing all the elements of I1 (contiguous sequence from 0 to N) not present in I2 (a...
Definition: tuple.hh:114
bool all(Bool &&...values)
Whether all the values evaluate as true.
Definition: tuple.hh:446
typename concat_index_sequence< S1, S2 >::type concat_sequence
Definition: tuple.hh:100
auto reverse_tuple(const std::tuple< Ts... > &t) -> decltype(reverse_tuple(t, make_index_sequence< sizeof...(Ts)>()))
Definition: tuple.hh:315
void hash_combine(std::size_t &seed, const T &v)
Definition: functional.hh:48
bool operator()(Bool &&...values)
Definition: tuple.hh:463
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
Definition: tuple.hh:301
Test if (c) then F1 else F2 and get the value.
Definition: tuple.hh:398
static std::size_t hash_(const value_t &v, vcsn::detail::index_sequence< I... >)
Definition: tuple.hh:497
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:342
typename make_index_range< S, E >::type make_index_range_t
Definition: tuple.hh:88
void for_(const std::tuple< Ts... > &ts, Fun f)
Definition: tuple.hh:158
Whether some of the values evaluate as true.
Definition: tuple.hh:460
auto apply_impl_(Fun f, const std::tuple< Args... > &args, index_sequence< I... >) -> decltype(f(std::get< I >(args)...))
Definition: tuple.hh:205