emilib
tuple_util.hpp
1 // By Emil Ernerfeldt 2014-2016
2 // LICENSE:
3 // This software is dual-licensed to the public domain and under the following
4 // license: you are granted a perpetual, irrevocable license to copy, modify,
5 // publish, and distribute this file as you see fit.
6 // HISTORY:
7 // Created in 2014 for Ghostel.
8 
9 #pragma once
10 
11 #include <tuple>
12 
13 namespace emilib {
14 
15 template<int N>
16 class Int_ {};
17 
18 namespace detail
19 {
20  // just to keep things concise and readable
21 #define ENABLE_IF(x) typename std::enable_if<(x), bool>::type
22 
23  // base case
24  template <std::size_t N, typename... Args, typename Iterator>
25  ENABLE_IF(N == 0) iterate(std::tuple<Args...>&, Iterator&&)
26  {
27  return true;
28  }
29 
30  // recursive case
31  template <std::size_t N, typename... Args, typename Iterator>
32  ENABLE_IF(N >= 1) iterate(std::tuple<Args...>& tup, Iterator&& it)
33  {
34  if (iterate<N - 1>(tup, it)) {
35  auto&& val = std::get<N-1>(tup);
36  return it( Int_<N-1>(), val );
37  } else {
38  return false;
39  }
40  }
41 
42  // const version:
43 
44  // base case
45  template <std::size_t N, typename... Args, typename Iterator>
46  ENABLE_IF(N == 0) iterate(const std::tuple<Args...>&, Iterator&)
47  {
48  return true;
49  }
50 
51  // recursive case
52  template <std::size_t N, typename... Args, typename Iterator>
53  ENABLE_IF(N >= 1) iterate(const std::tuple<Args...>& tup, Iterator& it)
54  {
55  if (iterate<N - 1>(tup, it)) {
56  auto&& val = std::get<N-1>(tup);
57  return it( Int_<N-1>(), val );
58  } else {
59  return false;
60  }
61  }
62 }
63 
72 template<typename Func, typename... Args>
73 bool for_each_tuple(std::tuple<Args...>& tup, Func&& func)
74 {
75  return detail::iterate<sizeof...(Args)>(tup, func);
76 }
77 
79 template<typename Func, typename... Args>
80 bool for_each_tuple(const std::tuple<Args...>& tup, Func&& func)
81 {
82  return detail::iterate<sizeof...(Args)>(tup, func);
83 }
84 
85 // ------------------------------------------------
86 
87 template<std::size_t N>
88 struct TupleArrayRef {
89  template<class Tuple>
90  static auto ref_to_members(Tuple&& tup, int ix)
91  {
92  return std::tuple_cat(TupleArrayRef<N-1>::ref_to_members(tup, ix),
93  std::tie( std::get<N-1>(tup)[ix] ) );
94  }
95 
96 };
97 
98 template<>
99 struct TupleArrayRef<0> {
100  template<class Tuple>
101  static std::tuple<> ref_to_members(Tuple&&, int)
102  {
103  // done
104  return std::tuple<>();
105  }
106 };
107 
108 // ------------------------------------------------
109 
110 } // namespace emilib
111 
112 namespace std {
113 namespace {
114 
119  template <class T>
120  inline void hash_combine(std::size_t& seed, T const& v)
121  {
122  seed ^= hash<T>()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
123  }
124 
126  template <class Tuple, size_t Index = std::tuple_size<Tuple>::value - 1>
127  struct HashValueImpl
128  {
129  static void apply(size_t& seed, Tuple const& tuple)
130  {
131  HashValueImpl<Tuple, Index-1>::apply(seed, tuple);
132  hash_combine(seed, get<Index>(tuple));
133  }
134  };
135 
136  template <class Tuple>
137  struct HashValueImpl<Tuple,0>
138  {
139  static void apply(size_t& seed, Tuple const& tuple)
140  {
141  hash_combine(seed, get<0>(tuple));
142  }
143  };
144 } // anonymous namespace
145 
148 template <typename ... TT>
149 struct hash<std::tuple<TT...>>
150 {
151  size_t operator()(std::tuple<TT...> const& tt) const
152  {
153  size_t seed = 0;
154  HashValueImpl<std::tuple<TT...>>::apply(seed, tt);
155  return seed;
156  }
157 
158 };
159 
160 } // namespace std
Definition: dual.hpp:249
Definition: tuple_util.hpp:16
Definition: tuple_util.hpp:88
Definition: coroutine.hpp:18