All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
subset_iterator.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
18 
19 #include <boost/iterator/filter_iterator.hpp>
20 #include <boost/iterator/transform_iterator.hpp>
21 #include <boost/range/iterator_range.hpp>
22 
23 #ifndef PAAL_SUBSET_ITERATOR_HPP
24 #define PAAL_SUBSET_ITERATOR_HPP
25 
26 namespace paal {
27 namespace data_structures {
32 template <int k, typename Iterator>
34  : private subsets_iterator_engine<k - 1, Iterator> {
35  protected:
41  Iterator get_begin() { return m_begin; }
42 
48  Iterator get_end() { return base::get_end(); }
49 
53  void set_to_end() {
54  m_begin = get_end();
56  }
57 
58  public:
59  using base = subsets_iterator_engine<k - 1, Iterator>;
60 
67  subsets_iterator_engine(Iterator begin, Iterator end) : base(begin, end) {
68  if (k == 1) {
69  m_begin = begin;
70  } else {
71  auto baseBegin = base::get_begin();
72  if (baseBegin != end) {
73  m_begin = ++baseBegin;
74  if (m_begin == end) {
75  // when we are at the end all iterators are set to m_end
77  }
78  } else {
79  // when we are at the end all iterators are set to m_end
80  set_to_end();
81  }
82  }
83  }
84 
85  subsets_iterator_engine() = default;
86 
92  bool next() {
93  ++m_begin;
94  while (m_begin == get_end()) {
95  if (base::next()) {
96  m_begin = base::get_begin();
97  if (m_begin == get_end()) {
98  // when we are at the end all iterators are set to m_end
100  return false;
101  }
102  ++m_begin;
103  } else {
104  return false;
105  }
106  }
107  return true;
108  }
109 
110  // TODO copy paste (combine_iterator)
121  template <typename F, typename... Args>
122  auto call(F f, Args &&... args) const->decltype(std::declval<base>().call(
123  std::move(f), std::forward<Args>(args)..., *std::declval<Iterator>())) {
124  return base::call(std::move(f), *m_begin, std::forward<Args>(args)...);
125  }
126 
135  friend bool operator==(const subsets_iterator_engine &left,
136  const subsets_iterator_engine &right) {
137  return left.m_begin == right.m_begin &&
138  static_cast<base>(left) == static_cast<base>(right);
139  }
140 
141  private:
142  Iterator m_begin;
143 };
144 
151 template <typename Iterator> class subsets_iterator_engine<0, Iterator> {
152  protected:
159  subsets_iterator_engine(Iterator begin, Iterator end) : m_end(end) {}
160 
161  subsets_iterator_engine() = default;
162 
168  Iterator get_begin() { return m_end; }
169 
175  Iterator get_end() { return m_end; }
176 
180  void set_to_end() {}
181 
182  public:
188  bool next() const { return false; }
189 
200  template <typename F, typename... Args>
201  auto call(F f,
202  Args &&... args) const->decltype(f(std::forward<Args>(args)...)) {
203  return f(std::forward<Args>(args)...);
204  }
205 
214  friend bool operator==(const subsets_iterator_engine &left,
215  const subsets_iterator_engine &right) {
216  return true;
217  }
218 
219  private:
220  Iterator m_end;
221 };
222 
233 template <int k, typename Iterator>
235  Iterator e) {
237 }
238 
247 template <int k, typename Iterator, typename Joiner = make_tuple>
248 class subsets_iterator : public boost::iterator_facade<
249  subsets_iterator<k, Iterator, Joiner>,
250  puretype(
251  (subsets_iterator_engine<k, Iterator>().call(std::declval<Joiner>())))
252  // , typename
253  // std::iterator_traits<Iterator>::iterator_category //TODO above forward
254  // tags are not yet implemented
255  ,
256  typename boost::forward_traversal_tag,
257  decltype(
258  subsets_iterator_engine<k, Iterator>().call(std::declval<Joiner>()))> {
259  public:
267  subsets_iterator(Iterator begin, Iterator end, Joiner joiner = Joiner{})
268  : m_joiner(joiner), m_iterator_engine(begin, end) {}
269 
273  subsets_iterator() = default;
274 
275  private:
276 
280  using ref = decltype(
281  subsets_iterator_engine<k, Iterator>().call(std::declval<Joiner>()));
282 
283  friend class boost::iterator_core_access;
284 
288  void increment() { m_iterator_engine.next(); }
289 
297  bool equal(subsets_iterator const &other) const {
298  return this->m_iterator_engine == other.m_iterator_engine;
299  }
300 
306  ref dereference() const { return m_iterator_engine.call(m_joiner); }
307  // TODO add random access support
308 
309  Joiner m_joiner;
310  subsets_iterator_engine<k, Iterator> m_iterator_engine;
311 };
312 
325 //TODO change name to subset_range()
326 template <int k, typename Iterator, typename Joiner = make_tuple>
327 boost::iterator_range<subsets_iterator<k, Iterator, Joiner>>
328 make_subsets_iterator_range(Iterator b, Iterator e, Joiner joiner = Joiner{}) {
329  typedef subsets_iterator<k, Iterator, Joiner> SI;
330  return boost::make_iterator_range(SI(b, e, joiner), SI(e, e, joiner));
331 }
332 
344 template <int k, typename Range, typename Joiner = make_tuple>
345 auto make_subsets_iterator_range(const Range & range, Joiner joiner = Joiner{}) {
346  return make_subsets_iterator_range<k>(std::begin(range), std::end(range), std::move(joiner));
347 }
348 
349 } // data_structures
350 } // paal
351 
352 #endif // PAAL_SUBSET_ITERATOR_HPP
bool next()
sets next configuration of iterators, pointing to next subset
subsets_iterator_engine(Iterator begin, Iterator end)
constructor
Iterator get_end()
get_end, returns end of the input collection
auto call(F f, Args &&...args) const -> decltype(f(std::forward< Args >(args)...))
actually calls f for given arguments
subsets_iterator_engine< k, Iterator > make_subsets_iterator_engine(Iterator b, Iterator e)
make for subsets_iterator_engine
auto call(F f, Args &&...args) const -> decltype(std::declval< base >().call(std::move(f), std::forward< Args >(args)...,*std::declval< Iterator >()))
calls arbitrary function f on (*m_curr)...
boost::iterator_range< subsets_iterator< k, Iterator, Joiner > > make_subsets_iterator_range(Iterator b, Iterator e, Joiner joiner=Joiner{})
make for subsets_iterator
Iterator to all k-subsets of given collection.
friend bool operator==(const subsets_iterator_engine &left, const subsets_iterator_engine &right)
operator==
subsets_iterator(Iterator begin, Iterator end, Joiner joiner=Joiner{})
constructor
Iterator get_end()
end is stored in the subsets_iterator_engine&lt;0&gt;
void set_to_end()
sets all iterators to m_end
friend bool operator==(const subsets_iterator_engine &left, const subsets_iterator_engine &right)
operator==, always true
subsets_iterator_engine(Iterator begin, Iterator end)
constructor
subsets_iterator()=default
default constructor represents end of the range