Appending ranges in loop

243 views Asked by At

I would like to concatenate ranges returned by function into one big range.Consider following code:

some_type_i_cant_figure_out bar() {
    typedef std::vector<int>::const_iterator iter;
    std::vector<int> aaa;
    /* fill some data into aaa*/
    some_type_i_cant_figure_out cc;
    for (int i = 0; i < aaa.size(); ++i) {
    std::pair<iter, iter> bbb = foo(aaa, i);
    ccc = boost::join(ccc, bbb);
    }
    return ccc;
}

What I'm trying to achieve:
The aaa vector is huge and foo may return quite big ranges. Of course I can just create copies of all elements in range into new vector of integers and return it. It is inefficient, wasting memory and time. So I would like return one boost::joined_range. In worst case, I can live with vector of ranges, but it would be too simple and not that elegant :) besides the joined_range isnt default constructible (which is a problematic for this example implementation) what would be the return value type? the temp variable (ccc) type and what would be the correct and elegant way to achieve the above?

1

There are 1 answers

7
sehe On BEST ANSWER

First off, the end result of your code would appear to be similar to just

auto cc(aaa);
boost::stable_sort(cc);

(Assuming, from your sample code, that aaa contains integers in the range [0..size()-1))

If you can afford to simply copy, just use a backinsert iterator:

std::vector<int> cc;
for (size_t i = 0; i < aaa.size(); ++i)
    boost::copy(boost::equal_range(aaa, i), back_inserter(cc));

Otherwise, you can hide the accumulating joins by using any_range:

boost::any_range<int, boost::forward_traversal_tag, int> r;
for (size_t i = 0; i < aaa.size(); ++i)
    r = boost::join(r, boost::equal_range(aaa, i));

Live On Coliru

#include <boost/range/any_range.hpp>
#include <boost/range/join.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>

int main() {
    std::vector<int> const aaa { 1,1,1,4,5,5,9,42,42,42,42,42,42 };

    boost::any_range<int, boost::forward_traversal_tag, int> r;
    for (size_t i = 0; i < aaa.size(); ++i)
        r = boost::join(r, boost::equal_range(aaa, i));

    boost::copy(r, std::ostream_iterator<int>(std::cout << "result: ", " "));
}

Prints

result: 1 1 1 4 5 5 9