18 #include <boost/iterator/filter_iterator.hpp>
19 #include <boost/iterator/transform_iterator.hpp>
20 #include <boost/iterator/iterator_facade.hpp>
21 #include <boost/range/empty.hpp>
23 #ifndef PAAL_COMBINE_ITERATOR_HPP
24 #define PAAL_COMBINE_ITERATOR_HPP
27 namespace data_structures {
43 template <
typename Range,
typename... RangesRest>
49 using Iterator =
typename boost::range_iterator<Range>::type;
58 :
base(rest...), m_begin(std::begin(range)), m_curr(std::begin(range)),
59 m_end(std::end(range)) {}
71 if (m_curr == m_end) {
89 template <
typename F,
typename... Args>
90 auto call(
F f, Args &&... args)->decltype(std::declval<base>().
call(
91 std::move(f), std::forward<Args>(args)..., *std::declval<Iterator>())) {
92 return base::call(std::move(f), std::forward<Args>(args)..., *m_curr);
105 return left.m_begin == right.m_begin && left.m_end == right.m_end &&
106 left.m_curr == right.m_curr &&
107 static_cast<base>(left) == static_cast<base>(right);
138 template <
typename F,
typename... Args>
139 auto call(
F f, Args &&... args)->decltype(f(std::forward<Args>(args)...)) {
140 return f(std::forward<Args>(args)...);
159 template <
typename T>
using rem_ref =
typename std::remove_reference<T>::type;
170 template <
typename... Ranges>
171 combine_iterator_engine<detail::rem_ref<Ranges>...>
185 template <
typename Joiner,
typename... Ranges>
187 combine_iterator<Joiner, Ranges...>,
188 puretype(combine_iterator_engine<Ranges...>().call(std::declval<Joiner>())),
189 boost::forward_traversal_tag
193 combine_iterator_engine<Ranges...>().call(std::declval<Joiner>()))> {
202 : m_joiner(joiner), m_iterator_engine(ranges...),
203 m_end(sizeof...(Ranges) ? is_empty(ranges...) : true) {}
221 template <
typename Range,
typename... RangesRest>
222 bool is_empty(
const Range &range,
const RangesRest &... rest) {
223 if (boost::empty(range)) {
226 return is_empty(rest...);
235 bool is_empty() {
return false; }
237 using ref = decltype(
238 combine_iterator_engine<Ranges...>().call(std::declval<Joiner>()));
240 friend class boost::iterator_core_access;
246 if (!m_iterator_engine.next()) {
259 return this->m_end == other.m_end &&
261 this->m_iterator_engine == other.m_iterator_engine);
269 ref dereference()
const {
return m_iterator_engine.call(m_joiner); }
272 mutable combine_iterator_engine<Ranges...> m_iterator_engine;
286 template <
typename Joiner,
typename... Ranges>
287 combine_iterator<Joiner, detail::rem_ref<Ranges>...>
298 #endif // PAAL_COMBINE_ITERATOR_HPP
bool next()
move iterators to the next position
combine_iterator iterates through all combinations of values from given ranges and returns them joine...
combine_iterator()
default constructor represents end of the range
friend bool operator==(const combine_iterator_engine &left, const combine_iterator_engine &right)
operator==, always true
bool next()
no next configuration
class representing set of ranges with two operation next and call
combine_iterator_engine(Range &range, RangesRest &...rest)
constructor
auto call(F f, Args &&...args) -> decltype(f(std::forward< Args >(args)...))
actually calls function f
combine_iterator(Joiner joiner, Ranges &...ranges)
constructor
combine_iterator< Joiner, detail::rem_ref< Ranges >...> make_combine_iterator(Joiner joiner, Ranges &&...ranges)
make for combine_iterator
auto call(F f, Args &&...args) -> decltype(std::declval< base >().call(std::move(f), std::forward< Args >(args)...,*std::declval< Iterator >()))
calls arbitrary function f on (*m_curr)...
combine_iterator_engine< detail::rem_ref< Ranges >...> make_combine_iterator_engine(Ranges &&...ranges)
make for combine_iterator_engine
friend bool operator==(const combine_iterator_engine &left, const combine_iterator_engine &right)
operator==