Range Iteration

If I have a range of ranges, is there a way to combine them together and iterate over them as if they were a single range?

By range, I mean any pair of containers or iterators. Mostly like boost ranges . Boost already has a function for combining two ranges together with boost :: join, but this function cannot join an arbitrary number of ranges.

Basically, I'm looking for a way to do what the many function does in this piece of code:

 std::vector<std::vector<int>> n = {{0, 1}, {2, 3}}; for (auto i : many(n)) std::cout << i << '\n'; 

Which will output 0, 1, 2, 3.

In C #, I had SelectMany that could do this.

+4
source share
1 answer

Here is an example of a smoothing iterator used with a range for (taken from here and added boost::make_iterator_range to display the range version) (work still needs to be done though):

 #include <boost/iterator/iterator_adaptor.hpp> #include <boost/range.hpp> #include <iostream> #include <vector> #include <algorithm> #include <iterator> #include <string> #include <utility> template <typename Iter> class flattening_iterator : public boost::iterator_adaptor< flattening_iterator<Iter>, Iter, typename Iter::value_type::iterator::value_type, boost::forward_traversal_tag, typename Iter::value_type::iterator::value_type > { private: using super_t = boost::iterator_adaptor< flattening_iterator<Iter>, Iter, typename Iter::value_type::iterator::value_type, boost::forward_traversal_tag, typename Iter::value_type::iterator::value_type >; using inner_iterator = typename Iter::value_type::iterator; public: flattening_iterator(Iter it) : super_t(it), inner_begin(), inner_end(), outer_end(it) {} flattening_iterator(Iter begin, Iter end) : super_t(begin), inner_begin((*begin).begin()), inner_end((*begin).end()), outer_end(end) {} using value_type = typename Iter::value_type::iterator::value_type; private: friend class boost::iterator_core_access; inner_iterator inner_begin; inner_iterator inner_end; Iter outer_end; void increment() { if (this->base_reference() == outer_end) return; // At the end ++inner_begin; if (inner_begin == inner_end) { ++this->base_reference(); inner_begin = (*this->base_reference()).begin(); inner_end = (*this->base_reference()).end(); } } value_type dereference() const { return *inner_begin; } }; template <typename Iter> auto flat_iter(Iter it) -> flattening_iterator<Iter> { return flattening_iterator<Iter>(it); } template <typename Iter> auto flat_iter(Iter begin, Iter end) -> flattening_iterator<Iter> { return flattening_iterator<Iter>(begin, end); } template <typename Cont> auto flatten(Cont& c) -> boost::iterator_range<flattening_iterator<decltype(std::declval<Cont>().begin())>> { return boost::make_iterator_range(flat_iter(c.begin(), c.end()), flat_iter(c.end())); } int main() { std::vector<std::vector<int>> v1{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; for (auto i : flatten(v1)) { std::cout << i << ' '; } } 

Output

1 2 3 4 5 6 7 8 9

+2
source

All Articles