Awali
Another Weighted Automata library
zip_maps.hh
Go to the documentation of this file.
1 // This file is part of Awali.
2 // Copyright 2016-2022 Sylvain Lombardy, Victor Marsault, Jacques Sakarovitch
3 //
4 // Awali is a free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef AWALI_MISC_ZIP_MAPS_HH
18 # define AWALI_MISC_ZIP_MAPS_HH
19 
20 # include <cassert>
21 # include <type_traits>
22 
23 #include <awali/sttc/misc/raise.hh> // pass
24 #include <awali/common/tuple.hh>
25 
26 namespace awali {
27  namespace sttc {
28  namespace internal {
29 
30  struct as_tuple {};
31  struct as_pair {};
32 
33  template <typename Dereference = as_tuple, typename... Maps>
34  struct zipped_maps
35  {
37  using maps_t = std::tuple<Maps...>;
38 
40  template <std::size_t... I>
42 
45 
46  zipped_maps(Maps... maps)
47  : maps_(maps...)
48  {}
49 
50  zipped_maps(const maps_t& maps)
51  : maps_(maps)
52  {}
53 
55  struct iterator
56  {
58  = std::tuple<typename std::remove_reference<Maps>::type::const_iterator...>;
59  using values_t
60  = std::tuple<typename std::remove_reference<Maps>::type::value_type...>;
61  // FIXME: we should be using ::reference, but I can't get it to
62  // work with const.
64  = std::tuple<const typename std::remove_reference<Maps>::type::value_type&...>;
65  using ranges_t
66  = std::tuple<std::pair<typename std::remove_reference<Maps>::type::const_iterator,
67  typename std::remove_reference<Maps>::type::const_iterator>...>;
69  using key_t
70  = typename std::remove_const<typename std::tuple_element<0, values_t>::type::first_type>::type;
72  using mapped_t
73  = std::tuple<const typename std::remove_reference<Maps>::type::mapped_type&...>;
74 
76  typename std::remove_reference<Maps>::type::const_iterator... is,
77  typename std::remove_reference<Maps>::type::const_iterator... ends)
78  : zip_(zip)
79  , is_(is...)
80  , ends_(ends...)
81  , is_done_(false)
82  {
83  align_();
84  }
85 
88 
94  bool is_done_;
95 
98  {
99  if (!is_done_)
100  {
101  ++std::get<0>(is_);
102  align_();
103  }
104  return *this;
105  }
106 
107  bool operator!=(const iterator& that) const
108  {
109  return not_equal_(that, indices_t{});
110  }
111 
112  std::pair<key_t, mapped_t> dereference_(as_pair)
113  {
114  return dereference_as_pair();
115  }
116 
118  {
119  return dereference_as_tuple();
120  }
121 
122  auto operator*()
123  // GCC wants "this->", clang does not need it.
124  -> decltype(this->dereference_(Dereference()))
125  {
126  return dereference_(Dereference());
127  }
128 
131  {
132  return dereference_(indices_t{});
133  }
134 
136  std::pair<key_t, mapped_t> dereference_as_pair()
137  {
138  return {dereference_first_(), dereference_second_(indices_t{})};
139  }
140 
141  private:
143  void done_()
144  {
145  is_done_ = true;
146  is_ = ends_;
147  }
148 
153  void align_()
154  {
155  if (std::get<0>(is_) == std::get<0>(ends_))
156  done_();
157  if (!is_done_)
158  {
159  key_t k = std::get<0>(is_)->first;
160  while (!is_done_)
161  {
162  auto k2 = align_(k, indices_t{});
163  if (is_done_ || k == k2)
164  break;
165  else
166  k = k2;
167  }
168  }
169  }
170 
173  template <std::size_t... I>
174  key_t align_(key_t k, seq<I...>)
175  {
176  using swallow = int[];
177  (void) swallow{ (!is_done_ && (k = align_<I>(k), false))... };
178  return k;
179  }
180 
183  template<std::size_t I>
184  key_t align_(key_t k)
185  {
186  assert(!is_done_);
187  auto& first = std::get<I>(is_);
188 
189  // Look for the beginning of the range for key k.
190  // first = second;
191  while (first != std::get<I>(ends_) && first->first < k)
192  ++first;
193  if (first == std::get<I>(ends_))
194  // Nothing left.
195  done_();
196  else
197  // Found something, return its key.
198  k = first->first;
199  return k;
200  }
201 
202  template <std::size_t... I>
203  bool not_equal_(const iterator& that, seq<I...>) const
204  {
205  for (auto n: {(std::get<I>(is_) != std::get<I>(that.is_))...})
206  if (n)
207  return true;
208  return false;
209  }
210 
212  key_t dereference_first_() const
213  {
214  return std::get<0>(is_)->first;
215  }
216 
218  template <std::size_t... I>
219  mapped_t dereference_second_(seq<I...>) const
220  {
221  // clang 3.4 on top of libstdc++ wants this ctor to be
222  // explicitly called.
223  return mapped_t{(std::get<I>(is_)->second)...};
224  }
225 
227  template <std::size_t... I>
228  references_t dereference_(seq<I...>) const
229  {
230  // clang 3.4 on top of libstdc++ wants this ctor to be
231  // explicitly called:
232 
233  // sttc/misc/zip-maps.hh:275:16: error: chosen constructor is
234  // explicit in copy-initialization
235  // return {(*std::get<I>(is_))...};
236  // ^~~~~~~~~~~~~~~~~~~~~~~~
237  return references_t{(*std::get<I>(is_))...};
238  }
239  };
240 
242  {
243  auto res = begin_(indices_t{});
244  return res;
245  }
246 
248  {
249  return end_(indices_t{});
250  }
251 
252  private:
253  template <std::size_t... I>
254  iterator begin_(seq<I...>)
255  {
256  return iterator(*this,
257  std::get<I>(maps_).begin()...,
258  std::get<I>(maps_).end()...);
259  }
260 
261  template <std::size_t... I>
262  iterator end_(seq<I...>)
263  {
264  return iterator(*this,
265  std::get<I>(maps_).end()...,
266  std::get<I>(maps_).end()...);
267  }
268 
269  maps_t maps_;
270  };
271 
272  template <typename Dereference = as_pair, typename... Maps>
273  zipped_maps<Dereference, Maps...>
274  zip_maps(Maps&&... maps)
275  {
276  return {std::forward<Maps>(maps)...};
277  }
278 
279  template <typename Dereference = as_pair, typename... Maps>
280  zipped_maps<Dereference, Maps...>
281  zip_map_tuple(const std::tuple<Maps...>& maps)
282  {
283  return {maps};
284  }
285  }
286  }
287 }//end of ns awali::stc
288 
289 #endif // !AWALI_MISC_ZIP_MAPS_HH
Definition: tuple.hh:43
zip_sequences< Sequences... > zip(Sequences &&... seqs)
Definition: zip.hh:231
zipped_maps< Dereference, Maps... > zip_maps(Maps &&... maps)
Definition: zip_maps.hh:274
zipped_maps< Dereference, Maps... > zip_map_tuple(const std::tuple< Maps... > &maps)
Definition: zip_maps.hh:281
Definition: zip_maps.hh:31
Definition: zip_maps.hh:30
Main namespace of Awali.
Definition: ato.hh:22
Composite iterator.
Definition: zip_maps.hh:56
typename std::remove_const< typename std::tuple_element< 0, values_t >::type::first_type >::type key_t
Common key type.
Definition: zip_maps.hh:70
zipped_maps & zip_
The maps etc.
Definition: zip_maps.hh:87
iterator & operator++()
Advance to next position.
Definition: zip_maps.hh:97
std::pair< key_t, mapped_t > dereference_as_pair()
Return as <k1, <v1, v2...>>.
Definition: zip_maps.hh:136
auto operator*() -> decltype(this->dereference_(Dereference()))
Definition: zip_maps.hh:122
std::tuple< typename std::remove_reference< Maps >::type::value_type... > values_t
Definition: zip_maps.hh:60
std::tuple< const typename std::remove_reference< Maps >::type::value_type &... > references_t
Definition: zip_maps.hh:64
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:75
std::tuple< const typename std::remove_reference< Maps >::type::mapped_type &... > mapped_t
Tuple of mapped types.
Definition: zip_maps.hh:73
bool is_done_
Whether we reached the end.
Definition: zip_maps.hh:94
values_t dereference_(as_tuple)
Definition: zip_maps.hh:117
iterators_t ends_
The genuine ends.
Definition: zip_maps.hh:92
std::pair< key_t, mapped_t > dereference_(as_pair)
Definition: zip_maps.hh:112
std::tuple< typename std::remove_reference< Maps >::type::const_iterator... > iterators_t
Definition: zip_maps.hh:58
iterators_t is_
The current position.
Definition: zip_maps.hh:90
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:67
references_t dereference_as_tuple()
Return as <<k1, v1>, <k1, v2>, ...>.
Definition: zip_maps.hh:130
bool operator!=(const iterator &that) const
Definition: zip_maps.hh:107
Definition: zip_maps.hh:35
std::tuple< Maps... > maps_t
Type of the tuple of all the maps.
Definition: zip_maps.hh:37
awali::internal::make_index_sequence< sizeof...(Maps)> indices_t
Index sequence for our maps.
Definition: zip_maps.hh:44
iterator end()
Definition: zip_maps.hh:247
zipped_maps(const maps_t &maps)
Definition: zip_maps.hh:50
zipped_maps(Maps... maps)
Definition: zip_maps.hh:46
iterator begin()
Definition: zip_maps.hh:241