Concatenate multiple ranges without copying

1.3k views Asked by At

I want to concatenate multiple ranges (e.q.vectors) in to a single range without copying them to a new container, so that the performance is better.

It is for iterating over the whole range later.

#include <iostream>
#include <vector>

#include <boost/range/adaptors.hpp>
#include <boost/range.hpp>

const std::vector<int> vec1 = { 0, 1, 2, 3 };
const std::vector<int> vec2 = { 10, 11, 12, 13 };
const std::vector<int> vec3 = { 20, 21, 22, 23 };
const std::vector<int> vec4 = { 30, 31, 32, 33 };
std::vector< std::vector<int>> all{vec1, vec2, vec3, vec4};


int main() {
   auto range = boost::adaptors::transform( all, [&](auto &v) {
     return boost::make_iterator_range( v );  
   } );
   
   for( const auto &i:range) {
    std::cout << i << ", ";   
   }
}

The above prints this;

0123, 10111213, 20212223, 30313233,  

But what I actually want is this;

0, 1, 2, 3, 10, 11, 12, 13, 20, 21, 22, 23, 30, 31, 32, 33,  
3

There are 3 answers

0
GiantSpaceFlyingElvis On

One comment before i give my old-style answer. It is that you already copy all the vectors when you create all in the code above....

A potential solution is to have a vector of pointer to vector.

std::vector< std::vector<int>*> all;

then you push_back the address of all your vectors into the vector of vector. Only copying an address for each vector has less performance impact than copying the whole thing.

Then you scan the vector of vector using nested loop.

   for( auto temp:all)
     for (int element:*temp)
     {
      std::cout << element << ", ";   
     }
0
eerorika On

If you can use C++20 ranges rather than boost, then you could do:

auto range = all | std::views::join

Same works with the ranges-v3 library. Using ranges-v3 library, you could avoid creating all if that is desired:

auto range = ranges::views::concat(vec1, vec2, vec3, vec4);

With boost, you could do:

auto range =
    boost::join(vec1,
        boost::join(vec2,
            boost::join(vec3, vec4)
        )
    );
0
Ludovic Aubert On

There is actually a ranges::views::concat() coming up with C++23 2/3.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html