Vcsn  2.2a
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 
63  template <std::size_t S, std::size_t L>
65  : int_range<S, typename make_index_sequence<L>::type>
66  {};
67 
68  template <std::size_t S>
69  struct make_index_range<S, 0> : index_sequence<>{};
70  template <std::size_t S>
71  struct make_index_range<S, -1U> : index_sequence<>{};
72 
73  template <std::size_t S, std::size_t L>
75 
76  template <typename S1, typename S2>
78 
79  template <std::size_t... I1, std::size_t... I2>
81  : index_sequence<I1..., I2...>{};
82 
83  template <typename S1, typename S2>
85 
86  // There is a bug in clang making this one useless...
87  // The index sequence generated is always <0>
88  // Bug report:
89  // http://llvm.org/bugs/show_bug.cgi?id=14858
90  //template <typename... T>
91  //using index_sequence_for = make_index_sequence<sizeof...(T)>;
92 
97  template <typename S1, typename S2>
99 
100  template <std::size_t I1_1, std::size_t... I1, std::size_t... I2>
102  index_sequence<I1_1, I2...>>
103  {
104  using type =
107  };
108 
109  template <std::size_t I1_1, std::size_t I2_1,
110  std::size_t... I1, std::size_t... I2>
112  index_sequence<I2_1, I2...>>
113  {
114  using type =
118  };
119 
120  template <std::size_t I1_1, std::size_t... I1>
122  {
123  using type =
127  };
128 
129  template <>
131  {
132  using type = typename index_sequence<>::type;
133  };
134 
135  template <typename S1, typename S2>
136  using sequence_difference
137  = typename index_sequence_difference<typename S1::type,
138  typename S2::type>::type;
139 
140  template <typename Fun, typename... Ts>
141  inline void
142  for_(const std::tuple<Ts...>& ts, Fun f)
143  {
144  for_(f, ts, make_index_sequence<sizeof...(Ts)>());
145  }
146 
147  template <typename Fun, typename... Ts, size_t... I>
148  inline void
149  for_(Fun f,
150  const std::tuple<Ts...>& ts,
152  {
153  using swallow = int[];
154  (void) swallow{ (f(std::get<I>(ts)), 0)... };
155  }
156 
158  template <typename Fun, typename... Ts>
159  inline auto
160  map(const std::tuple<Ts...>& ts, Fun f)
161  -> decltype(map_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>()))
162  {
163  return map_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>());
164  }
165 
166  template <typename Fun, typename... Ts, size_t... I>
167  inline auto
168  map_tuple_(Fun f,
169  const std::tuple<Ts...>& ts,
171  -> decltype(map_variadic_(f, std::get<I>(ts)...))
172  {
173  return map_variadic_(f, std::get<I>(ts)...);
174  }
175 
176  template <typename Fun>
177  inline auto
179  -> decltype(std::make_tuple())
180  {
181  return std::make_tuple();
182  }
183 
184  template <typename Fun, typename T, typename... Ts>
185  inline auto
186  map_variadic_(Fun f, T t, Ts&&... ts)
187  -> decltype(std::tuple_cat(std::make_tuple(f(t)),
188  map_variadic_(f, ts...)))
189  {
190  // Enforce evaluation order from left to right.
191  auto r = f(t);
192  return std::tuple_cat(std::make_tuple(r), map_variadic_(f, ts...));
193  }
194 
195 
196  /*--------------------------------------------.
197  | Variadic Cartesian product of containers. |
198  `--------------------------------------------*/
199 
205  template <typename Fun>
206  inline void
207  cross(Fun f)
208  {
209  f();
210  }
211 
212  template <typename Fun,
213  typename Cont, typename... Conts>
214  inline void
215  cross(Fun f,
216  const Cont& head, const Conts&... tails)
217  {
218  for (const typename Cont::value_type& h: head)
219  cross([&](const typename Conts::value_type&... tails)
220  { f(h, tails...); },
221  tails...);
222  }
223 
224  template <typename Fun, typename... Ts, size_t... I>
225  inline void
227  const std::tuple<Ts...>& ts,
229  {
230  cross(f, std::get<I>(ts)...);
231  }
232 
233  template <typename Fun, typename... Ts>
234  inline void
235  cross_tuple(Fun f,
236  const std::tuple<Ts...>& ts)
237  {
238  cross_tuple_(f, ts, make_index_sequence<sizeof...(Ts)>());
239  }
240 
241 
242 
243 #if 0
244 
245  /*-----------------.
246  | make_gcc_tuple. |
247  `-----------------*/
248 
249  // This does not work, I don't understand why. If you know, please
250  // let me (AD) know.
251  inline auto
253  -> std::tuple<>
254  {
255  return {};
256  }
257 
258  template <typename T, typename... Ts>
259  inline auto
260  make_gcc_tuple(T t, Ts&&... ts)
261  -> decltype(std::tuple_cat(make_gcc_tuple(std::forward<Ts>(ts)...), std::make_tuple(t)));
262 
263  template <typename T, typename... Ts>
264  inline auto
265  make_gcc_tuple(T t, Ts&&... ts)
266  -> decltype(std::tuple_cat(make_gcc_tuple(std::forward<Ts>(ts)...), std::make_tuple(t)))
267  {
268  return std::tuple_cat(make_gcc_tuple(std::forward<Ts>(ts)...), std::make_tuple(t));
269  }
270 
271 #endif
272 
273 
274  /*----------------.
275  | reverse_tuple. |
276  `----------------*/
277 
278  template <typename... Ts>
279  inline auto
280  reverse_tuple(const std::tuple<Ts...>& t)
281  -> decltype(reverse_tuple(t, make_index_sequence<sizeof...(Ts)>()))
282  {
283  return reverse_tuple(t, make_index_sequence<sizeof...(Ts)>());
284  }
285 
286  template <typename... Ts, std::size_t... I>
287  inline auto
288  reverse_tuple(const std::tuple<Ts...>& t, index_sequence<I...>)
289  -> decltype(std::make_tuple(std::get<sizeof...(Ts) - 1 - I>(t)...))
290  {
291  return std::make_tuple(std::get<sizeof...(Ts) - 1 - I>(t)...);
292  }
293 
296 #if VCSN_HAVE_CORRECT_LIST_INITIALIZER_ORDER
297  template <typename... Ts>
298  inline auto
299  make_gcc_tuple(Ts&&... ts)
300  -> decltype(std::make_tuple(std::forward<Ts>(ts)...))
301  {
302  return std::make_tuple(std::forward<Ts>(ts)...);
303  }
304 #else
305  template <typename... Ts>
306  inline auto
307  make_gcc_tuple(Ts&&... ts)
308  -> decltype(reverse_tuple(std::make_tuple(std::forward<Ts>(ts)...)))
309  {
310  return reverse_tuple(std::make_tuple(std::forward<Ts>(ts)...));
311  }
312 #endif
313 
314 
315  /*------------------------.
316  | print(tuple, ostream). |
317  `------------------------*/
318 
319  template <typename Tuple, std::size_t N>
321  {
322  static void print(const Tuple& t, std::ostream& o)
323  {
325  o << ", " << std::get<N-1>(t);
326  }
327  };
328 
329  template <typename Tuple>
330  struct tuple_printer<Tuple, 1>
331  {
332  static void print(const Tuple& t, std::ostream& o)
333  {
334  o << std::get<0>(t);
335  }
336  };
337 
338  template <typename... Args>
339  std::ostream& print(const std::tuple<Args...>& args, std::ostream& o)
340  {
341  o << '(';
342  tuple_printer<decltype(args), sizeof...(Args)>::print(args, o);
343  return o << ')';
344  }
345 
346 
347  // Compile-time logic
348  // See:
349  // http://stillmoreperfect.blogspot.fr/2010/03/template-metaprogramming-compile-time.html
350 
351  // Test if (c) then T1 else T2
352  template <bool c, typename T1, typename T2>
353  struct if_c { typedef T1 type; };
354 
355  template <typename T1, typename T2>
356  struct if_c<false, T1, T2> { typedef T2 type; };
357 
358  template <typename C, typename T1, typename T2>
359  struct if_ : if_c<C::value, T1, T2> {};
360 
362  template <bool c, typename F1, typename F2>
363  struct eval_if_c : if_c<c, F1, F2>::type {};
364 
365  template <typename C, typename F1, typename F2>
366  struct eval_if : if_<C, F1, F2>::type {};
367 
369  template <typename... F>
370  struct and_;
371 
372  template <typename F1, typename... F>
373  struct and_<F1, F...> : eval_if<F1, and_<F...>, std::false_type>::type {};
374 
375  template <typename F1>
376  struct and_<F1> : eval_if<F1, std::true_type, std::false_type>::type {};
377 
378  template <>
379  struct and_<> : std::true_type::type {};
380 
382  template <typename... F>
383  struct or_;
384 
385  template <typename F1, typename... F>
386  struct or_<F1, F...> : eval_if<F1, std::true_type, or_<F...>>::type { };
387 
388  template <typename F1>
389  struct or_<F1> : eval_if<F1, std::true_type, std::false_type>::type { };
390 
391  template <>
392  struct or_<> : std::true_type::type {};
393  }
394 
396  template <bool... B>
397  constexpr bool any_()
398  {
399  return detail::or_<bool_constant<B>...>::value;
400  }
401 
402  // Static evaluation of the 'and' of the template parameters
403  template <bool... B>
404  constexpr bool all_()
405  {
406  return detail::and_<bool_constant<B>...>::value;
407  }
408 
409  template <typename... Bool>
410  bool all(Bool&&... values)
411  {
412  bool res = true;
413  using swallow = int[];
414  (void) swallow
415  {
416  (res = res && values, 0)...
417  };
418  return res;
419  }
420 
421 }
422 
423 namespace std
424 {
425 
426  /*-------------------------.
427  | std::hash(tuple<T...>). |
428  `-------------------------*/
429 
430  template <typename... Elements>
431  struct hash<std::tuple<Elements...>>
432  {
433  using value_t = std::tuple<Elements...>;
434  using indices_t = vcsn::detail::make_index_sequence<sizeof...(Elements)>;
435 
436  std::size_t operator()(const value_t& v) const
437  {
438  return hash_(v, indices_t{});
439  }
440 
441  private:
442  template <std::size_t... I>
443  static std::size_t
445  {
446  std::size_t res = 0;
447  using swallow = int[];
448  (void) swallow
449  {
450  (vcsn::hash_combine(res, std::get<I>(v)), 0)...
451  };
452  return res;
453  }
454  };
455 }
void cross_tuple_(Fun f, const std::tuple< Ts... > &ts, index_sequence< I... >)
Definition: tuple.hh:226
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
And condition on several typenames.
Definition: tuple.hh:370
Or condition on several typenames.
Definition: tuple.hh:383
static std::size_t hash_(const value_t &v, vcsn::detail::index_sequence< I... >)
Definition: tuple.hh:444
typename concat_index_sequence< S1, S2 >::type concat_sequence
Definition: tuple.hh:84
void for_(const std::tuple< Ts... > &ts, Fun f)
Definition: tuple.hh:142
constexpr bool all_()
Definition: tuple.hh:404
std::tuple< Elements... > value_t
Definition: tuple.hh:433
static void print(const Tuple &t, std::ostream &o)
Definition: tuple.hh:322
std::ostream & print(const std::tuple< Args... > &args, std::ostream &o)
Definition: tuple.hh:339
auto map_variadic_(Fun) -> decltype(std::make_tuple())
Definition: tuple.hh:178
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:307
typename concat_index_sequence< index_sequence< I1_1 >, typename index_sequence_difference< index_sequence< I1... >, index_sequence<>>::type >::type type
Definition: tuple.hh:126
typename index_sequence_difference< index_sequence< I1... >, index_sequence< I2... >>::type type
Definition: tuple.hh:106
std::size_t operator()(const value_t &v) const
Definition: tuple.hh:436
std::string type(const automaton &a)
The implementation type of a.
Definition: others.cc:206
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:117
static void print(const Tuple &t, std::ostream &o)
Definition: tuple.hh:332
ValueSet::value_t tuple(const ValueSet &vs, const typename ValueSets::value_t &...v)
Definition: tuple.hh:43
void cross(Fun f)
Variadic Cartesian product of containers.
Definition: tuple.hh:207
Test if (c) then F1 else F2 and get the value.
Definition: tuple.hh:363
auto reverse_tuple(const std::tuple< Ts... > &t) -> decltype(reverse_tuple(t, make_index_sequence< sizeof...(Ts)>()))
Definition: tuple.hh:280
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:160
typename index_sequence_difference< typename S1::type, typename S2::type >::type sequence_difference
Definition: tuple.hh:138
auto map_tuple_(Fun f, const std::tuple< Ts... > &ts, index_sequence< I... >) -> decltype(map_variadic_(f, std::get< I >(ts)...))
Definition: tuple.hh:168
void cross_tuple(Fun f, const std::tuple< Ts... > &ts)
Definition: tuple.hh:235
bool all(Bool &&...values)
Definition: tuple.hh:410
STL namespace.
constexpr bool any_()
Static evaluation of the 'or' of the template parameters.
Definition: tuple.hh:397
typename make_index_range< S, L >::type make_index_range_t
Definition: tuple.hh:74
void hash_combine(std::size_t &seed, const T &v)
Definition: functional.hh:32
Get the list containing all the elements of I1 (contiguous sequence from 0 to N) not present in I2 (a...
Definition: tuple.hh:98
typename std::tuple_element< I, T >::type tuple_element_t
C++14.
Definition: tuple.hh:14
typename make_index_sequence< N >::type GenSeq
Definition: tuple.hh:44
Definition: a-star.hh:8