Vcsn  2.8
Be Rational
cross.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 
5 #include <boost/iterator/iterator_facade.hpp>
6 
7 #include <vcsn/misc/tuple.hh>
8 
9 namespace vcsn
10 {
15  template <typename... Sequences>
17  {
19 
21  using sequences_t = std::tuple<Sequences...>;
22 
24  template <std::size_t... I>
26 
28  static constexpr size_t size = sizeof...(Sequences);
29 
31  using indices_t = vcsn::detail::make_index_sequence<sizeof...(Sequences)>;
32 
34  template <typename Seq>
35  using seq_t = std::remove_reference_t<Seq>;
36 
38  using value_type
39  = std::tuple<typename seq_t<Sequences>::value_type...>;
40 
42  : sequences_(std::move(sequences))
43  {}
44 
45  cross_sequences(Sequences... sequences)
46  : sequences_(sequences...)
47  {}
48 
50  using const_iterators_t
51  = std::tuple<typename seq_t<Sequences>::const_iterator...>;
52 
54  using iterators_t
55  = std::tuple<typename seq_t<Sequences>::iterator...>;
56 
58  template <typename ValueType,
59  typename IteratorsType>
61  : public boost::iterator_facade<
62  cross_iterator<ValueType, IteratorsType>
63  , ValueType
64  , boost::forward_traversal_tag
65  , ValueType // Reference.
66  >
67  {
69  using iterators_type = IteratorsType;
70 
72  const iterators_type& begins, const iterators_type& ends)
73  : is_{is}
74  , begins_{begins}
75  , ends_{ends}
76  {
77  // If one of the ranges is empty, we are done already.
78  if (empty())
79  done_();
80  }
81 
83  : cross_iterator{is, is, ends}
84  {}
85 
86  template <typename OtherValue, typename OtherIterators>
88  : cross_iterator{that.is_, that.begins_, that.ends_}
89  {}
90 
97 
99  bool empty() const
100  {
101  return empty_(indices_t{});
102  }
103 
105  void increment()
106  {
107  if (increment_() == -1)
108  done_();
109  }
110 
111  bool equal(const cross_iterator& that) const
112  {
113  return equal_(that, indices_t{});
114  }
115 
117  {
118  return dereference_(indices_t{});
119  }
120 
121  private:
123 
124  template <std::size_t... I>
125  bool empty_(seq<I...>) const
126  {
127  for (auto n: {(std::get<I>(begins_) == std::get<I>(ends_))...})
128  if (n)
129  return true;
130  return false;
131  }
132 
134  void done_()
135  {
136  is_ = ends_;
137  }
138 
142  {
143  auto res = increment_(indices_t{});
144  // Reset all the iterators that are before the first one that could
145  // advance.
146  if (res != -1)
147  reset_up_to_(res);
148  return res;
149  }
150 
151  template <std::size_t... I>
153  {
154  int res = -1;
155  using swallow = int[];
156  (void) swallow
157  {
158  (res == -1
159  && std::get<size-1-I>(is_) != std::get<size-1-I>(ends_)
160  && ++std::get<size-1-I>(is_) != std::get<size-1-I>(ends_))
161  ? res = size-1-I
162  : 0
163  ...
164  };
165  return res;
166  }
167 
169  void reset_up_to_(int n)
170  {
171  reset_up_to_(n, indices_t{});
172  }
173 
174  template <std::size_t... I>
175  void reset_up_to_(size_t n, seq<I...>)
176  {
177  using swallow = int[];
178  (void) swallow
179  {
180  (n < I
181  && ((std::get<I>(is_) = std::get<I>(begins_)), true))...
182  };
183  }
184 
185  template <std::size_t... I>
186  bool equal_(const cross_iterator& that, seq<I...>) const
187  {
188  for (auto n: {(std::get<I>(is_) == std::get<I>(that.is_))...})
189  if (!n)
190  return false;
191  return true;
192  }
193 
195  template <std::size_t... I>
197  {
198  return value_type{(*std::get<I>(is_))...};
199  }
200  };
201 
204 
207 
209  self_t& skip_first(bool s = true)
210  {
211  skip_first_ = s;
212  return *this;
213  }
214 
216  {
217  auto res = cbegin_(indices_t{});
218  if (skip_first_)
219  ++res;
220  return res;
221  }
222 
224  {
225  return cend_(indices_t{});
226  }
227 
229  {
230  return cbegin();
231  }
232 
234  {
235  return cend();
236  }
237 
239  {
240  auto res = begin_(indices_t{});
241  if (skip_first_)
242  ++res;
243  return res;
244  }
245 
247  {
248  return end_(indices_t{});
249  }
250 
252  bool empty() const
253  {
254  return cbegin() == cend();
255  }
256 
257 
258  private:
259  template <std::size_t... I>
261  {
262  // FIXME: clang-3.5: std::cbegin/cend are not supported, yet.
263  using std::begin;
264  using std::end;
265  return {const_iterators_t{begin(std::get<I>(sequences_))...},
266  const_iterators_t{end(std::get<I>(sequences_))...}};
267  }
268 
269  template <std::size_t... I>
271  {
272  using std::end;
273  return {const_iterators_t{end(std::get<I>(sequences_))...},
274  const_iterators_t{end(std::get<I>(sequences_))...}};
275  }
276 
277  template <std::size_t... I>
279  {
280  using std::begin;
281  using std::end;
282  return {iterators_t{begin(std::get<I>(sequences_))...},
283  iterators_t{end(std::get<I>(sequences_))...}};
284  }
285 
286  template <std::size_t... I>
288  {
289  using std::end;
290  return {iterators_t{end(std::get<I>(sequences_))...},
291  iterators_t{end(std::get<I>(sequences_))...}};
292  }
293 
296 
298  bool skip_first_ = false;
299  };
300 
301  template <typename... Sequences>
302  cross_sequences<Sequences...>
303  cross(Sequences&&... seqs)
304  {
305  return {std::forward<Sequences>(seqs)...};
306  }
307 
308  template <typename... Sequences>
309  cross_sequences<Sequences...>
310  cross_tuple(const std::tuple<Sequences...>& seqs)
311  {
312  return {seqs};
313  }
314 }
IteratorsType iterators_type
Underlying iterators.
Definition: cross.hh:69
int increment_()
Move to the next position.
Definition: cross.hh:141
iterator end_(seq< I... >)
Definition: cross.hh:287
std::tuple< typename seq_t< Sequences >::iterator... > iterators_t
Tuple of iterators.
Definition: cross.hh:55
bool skip_first_
Whether to skip the initial element.
Definition: cross.hh:298
cross_iterator(const iterators_type &is, const iterators_type &begins, const iterators_type &ends)
Definition: cross.hh:71
bool empty() const
Whether the sequence is empty.
Definition: cross.hh:252
bool empty() const
Whether some of the range is empty.
Definition: cross.hh:99
Composite iterator.
Definition: cross.hh:60
sequences_t sequences_
The sequences we iterate upon.
Definition: cross.hh:295
void done_()
We have reached the end, move all the cursors to this end.
Definition: cross.hh:134
static constexpr size_t size
Number of sequences.
Definition: cross.hh:28
std::tuple< typename seq_t< Sequences >::const_iterator... > const_iterators_t
Tuple of const_iterators.
Definition: cross.hh:51
std::remove_reference_t< Seq > seq_t
The type of the underlying sequences, without reference.
Definition: cross.hh:35
cross_sequences(sequences_t sequences)
Definition: cross.hh:41
cross_sequences< Sequences... > cross_tuple(const std::tuple< Sequences... > &seqs)
Definition: cross.hh:310
auto tuple(const Auts &... as)
Build the (accessible part of the) tuple.
const_iterator cbegin() const
Definition: cross.hh:215
bool equal_(const cross_iterator &that, seq< I... >) const
Definition: cross.hh:186
iterators_type ends_
The ends.
Definition: cross.hh:96
iterators_type begins_
The begins.
Definition: cross.hh:94
iterator end()
Definition: cross.hh:246
const_iterator cend() const
Definition: cross.hh:223
bool equal(const cross_iterator &that) const
Definition: cross.hh:111
iterator begin_(seq< I... >)
Definition: cross.hh:278
void increment()
Advance to next position.
Definition: cross.hh:105
Build the static sequence of size_t [0, N[.
Definition: tuple.hh:56
Provide a range that allows to iterate over the cross product of the provided ranges.
Definition: cross.hh:16
Definition: a-star.hh:8
cross_sequences< Sequences... > cross(Sequences &&... seqs)
Definition: cross.hh:303
cross_iterator(cross_iterator< OtherValue, OtherIterators > const &that)
Definition: cross.hh:87
const_iterator cbegin_(seq< I... >) const
Definition: cross.hh:260
value_type dereference() const
Definition: cross.hh:116
iterators_type is_
The current position.
Definition: cross.hh:92
cross_sequences(Sequences... sequences)
Definition: cross.hh:45
A static list of size_t.
Definition: tuple.hh:32
std::tuple< typename seq_t< Sequences >::value_type... > value_type
The type of the members.
Definition: cross.hh:39
std::tuple< Sequences... > sequences_t
Type of the tuple of all the maps.
Definition: cross.hh:21
self_t & skip_first(bool s=true)
Whether to skip the first element.
Definition: cross.hh:209
iterator begin()
Definition: cross.hh:238
void reset_up_to_(size_t n, seq< I... >)
Definition: cross.hh:175
const_iterator begin() const
Definition: cross.hh:228
void reset_up_to_(int n)
Move beginning of ranges to their end, and align.
Definition: cross.hh:169
const_iterator end() const
Definition: cross.hh:233
STL namespace.
const_iterator cend_(seq< I... >) const
Definition: cross.hh:270
value_type dereference_(seq< I... >) const
Tuple of values.
Definition: cross.hh:196
return res
Definition: multiply.hh:399
bool empty_(seq< I... >) const
Definition: cross.hh:125
cross_iterator(const iterators_type &is, const iterators_type &ends)
Definition: cross.hh:82
friend class boost::iterator_core_access
Definition: cross.hh:122