Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
zip-maps.hh
Go to the documentation of this file.
1 #ifndef VCSN_MISC_ZIP_MAPS_HH
2 # define VCSN_MISC_ZIP_MAPS_HH
3 
4 # include <cassert>
5 # include <type_traits>
6 
7 # include <vcsn/misc/raise.hh> // pass
8 # include <vcsn/misc/tuple.hh>
9 
10 namespace vcsn
11 {
12 
13  struct as_tuple {};
14  struct as_pair {};
15 
16  template <typename Dereference = as_tuple, typename... Maps>
17  struct zipped_maps
18  {
20  using maps_t = std::tuple<Maps...>;
21 
23  template <std::size_t... I>
25 
27  using indices_t = vcsn::detail::make_index_sequence<sizeof...(Maps)>;
28 
29  zipped_maps(Maps... maps)
30  : maps_(maps...)
31  {}
32 
33  zipped_maps(const maps_t& maps)
34  : maps_(maps)
35  {}
36 
38  struct iterator
39  {
40  using iterators_t
41  = std::tuple<typename std::remove_reference<Maps>::type::const_iterator...>;
42  using values_t
43  = std::tuple<typename std::remove_reference<Maps>::type::value_type...>;
44  // FIXME: we should be using ::reference, but I can't get it to
45  // work with const.
46  using references_t
47  = std::tuple<const typename std::remove_reference<Maps>::type::value_type&...>;
48  using ranges_t
49  = std::tuple<std::pair<typename std::remove_reference<Maps>::type::const_iterator,
50  typename std::remove_reference<Maps>::type::const_iterator>...>;
52  using key_t
53  = typename std::remove_const<typename std::tuple_element<0, values_t>::type::first_type>::type;
55  using mapped_t
56  = std::tuple<const typename std::remove_reference<Maps>::type::mapped_type&...>;
57 
59  typename std::remove_reference<Maps>::type::const_iterator... is,
60  typename std::remove_reference<Maps>::type::const_iterator... ends)
61  : zip_(zip)
62  , is_(is...)
63  , ends_(ends...)
64  , is_done_(false)
65  {
66  align_();
67  }
68 
71 
77  bool is_done_;
78 
81  {
82  if (!is_done_)
83  {
84  ++std::get<0>(is_);
85  align_();
86  }
87  return *this;
88  }
89 
90  bool operator!=(const iterator& that) const
91  {
92  return not_equal_(that, indices_t{});
93  }
94 
95  std::pair<key_t, mapped_t> dereference_(as_pair)
96  {
97  return dereference_as_pair();
98  }
99 
101  {
102  return dereference_as_tuple();
103  }
104 
105  auto operator*()
106  // GCC wants "this->", clang does not need it.
107  -> decltype(this->dereference_(Dereference()))
108  {
109  return dereference_(Dereference());
110  }
111 
114  {
115  return dereference_(indices_t{});
116  }
117 
119  std::pair<key_t, mapped_t> dereference_as_pair()
120  {
122  }
123 
124  private:
126  void done_()
127  {
128  is_done_ = true;
129  is_ = ends_;
130  }
131 
136  void align_()
137  {
138  if (std::get<0>(is_) == std::get<0>(ends_))
139  done_();
140  if (!is_done_)
141  {
142  key_t k = std::get<0>(is_)->first;
143  while (!is_done_)
144  {
145  auto k2 = align_(k, indices_t{});
146  if (is_done_ || k == k2)
147  break;
148  else
149  k = k2;
150  }
151  }
152  }
153 
156  template <std::size_t... I>
158  {
159  using swallow = int[];
160  (void) swallow{ (!is_done_ && (k = align_<I>(k), false))... };
161  return k;
162  }
163 
166  template<std::size_t I>
168  {
169  assert(!is_done_);
170  auto& first = std::get<I>(is_);
171 
172  // Look for the beginning of the range for key k.
173  // first = second;
174  while (first != std::get<I>(ends_) && first->first < k)
175  ++first;
176  if (first == std::get<I>(ends_))
177  // Nothing left.
178  done_();
179  else
180  // Found something, return its key.
181  k = first->first;
182  return k;
183  }
184 
185  template <std::size_t... I>
186  bool not_equal_(const iterator& that, seq<I...>) const
187  {
188  for (auto n: {(std::get<I>(is_) != std::get<I>(that.is_))...})
189  if (n)
190  return true;
191  return false;
192  }
193 
196  {
197  return std::get<0>(is_)->first;
198  }
199 
201  template <std::size_t... I>
203  {
204  // clang 3.4 on top of libstdc++ wants this ctor to be
205  // explicitly called.
206  return mapped_t{(std::get<I>(is_)->second)...};
207  }
208 
210  template <std::size_t... I>
212  {
213  // clang 3.4 on top of libstdc++ wants this ctor to be
214  // explicitly called:
215 
216  // vcsn/misc/zip-maps.hh:275:16: error: chosen constructor is
217  // explicit in copy-initialization
218  // return {(*std::get<I>(is_))...};
219  // ^~~~~~~~~~~~~~~~~~~~~~~~
220  return references_t{(*std::get<I>(is_))...};
221  }
222  };
223 
225  {
226  auto res = begin_(indices_t{});
227  return res;
228  }
229 
231  {
232  return end_(indices_t{});
233  }
234 
235  private:
236  template <std::size_t... I>
238  {
239  return iterator(*this,
240  std::get<I>(maps_).begin()...,
241  std::get<I>(maps_).end()...);
242  }
243 
244  template <std::size_t... I>
246  {
247  return iterator(*this,
248  std::get<I>(maps_).end()...,
249  std::get<I>(maps_).end()...);
250  }
251 
253  };
254 
255  template <typename Dereference = as_pair, typename... Maps>
256  zipped_maps<Dereference, Maps...>
257  zip_maps(Maps&&... maps)
258  {
259  return {std::forward<Maps>(maps)...};
260  }
261 
262  template <typename Dereference = as_pair, typename... Maps>
263  zipped_maps<Dereference, Maps...>
264  zip_map_tuple(const std::tuple<Maps...>& maps)
265  {
266  return {maps};
267  }
268 }
269 
270 #endif // !VCSN_MISC_ZIP_MAPS_HH
std::tuple< std::pair< typename std::remove_reference< Maps >::type::const_iterator, typename std::remove_reference< Maps >::type::const_iterator >...> ranges_t
Definition: zip-maps.hh:50
zipped_maps(Maps...maps)
Definition: zip-maps.hh:29
iterators_t is_
The current position.
Definition: zip-maps.hh:73
key_t dereference_first_() const
The common key.
Definition: zip-maps.hh:195
iterator & operator++()
Advance to next position.
Definition: zip-maps.hh:80
iterator begin_(seq< I...>)
Definition: zip-maps.hh:237
void align_()
Align all iterators on the first common key.
Definition: zip-maps.hh:136
zipped_maps(const maps_t &maps)
Definition: zip-maps.hh:33
auto operator*() -> decltype(this->dereference_(Dereference()))
Definition: zip-maps.hh:105
std::tuple< const typename std::remove_reference< Maps >::type::mapped_type &...> mapped_t
Tuple of mapped types.
Definition: zip-maps.hh:56
std::pair< key_t, mapped_t > dereference_as_pair()
Return as >.
Definition: zip-maps.hh:119
Composite iterator.
Definition: zip-maps.hh:38
std::tuple< typename std::remove_reference< Maps >::type::value_type...> values_t
Definition: zip-maps.hh:43
bool is_done_
Whether we reached the end.
Definition: zip-maps.hh:77
bool not_equal_(const iterator &that, seq< I...>) const
Definition: zip-maps.hh:186
zip_sequences< Sequences...> zip(Sequences &&...seqs)
Definition: zip.hh:223
typename std::remove_const< typename std::tuple_element< 0, values_t >::type::first_type >::type key_t
Common key type.
Definition: zip-maps.hh:53
zipped_maps< Dereference, Maps...> zip_map_tuple(const std::tuple< Maps...> &maps)
Definition: zip-maps.hh:264
mapped_t dereference_second_(seq< I...>) const
The associated tuple of values.
Definition: zip-maps.hh:202
iterator begin()
Definition: zip-maps.hh:224
std::tuple< typename std::remove_reference< Maps >::type::const_iterator...> iterators_t
Definition: zip-maps.hh:41
zipped_maps & zip_
The maps etc.
Definition: zip-maps.hh:70
references_t dereference_as_tuple()
Return as <, , ...>.
Definition: zip-maps.hh:113
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:329
iterator(zipped_maps &zip, typename std::remove_reference< Maps >::type::const_iterator...is, typename std::remove_reference< Maps >::type::const_iterator...ends)
Definition: zip-maps.hh:58
iterators_t ends_
The genuine ends.
Definition: zip-maps.hh:75
std::tuple< Maps...> maps_t
Type of the tuple of all the maps.
Definition: zip-maps.hh:20
std::pair< key_t, mapped_t > dereference_(as_pair)
Definition: zip-maps.hh:95
key_t align_(key_t k, seq< I...>)
Try to align all the ranges to support key k.
Definition: zip-maps.hh:157
key_t align_(key_t k)
Given the current candidate key, try to find the proper range for I.
Definition: zip-maps.hh:167
references_t dereference_(seq< I...>) const
Tuple of pairs.
Definition: zip-maps.hh:211
void done_()
We have reached the end, move all the cursors to this end.
Definition: zip-maps.hh:126
values_t dereference_(as_tuple)
Definition: zip-maps.hh:100
zipped_maps< Dereference, Maps...> zip_maps(Maps &&...maps)
Definition: zip-maps.hh:257
iterator end()
Definition: zip-maps.hh:230
bool operator!=(const iterator &that) const
Definition: zip-maps.hh:90
std::tuple< const typename std::remove_reference< Maps >::type::value_type &...> references_t
Definition: zip-maps.hh:47
iterator end_(seq< I...>)
Definition: zip-maps.hh:245