Richard
Richard

Reputation: 61479

Iterable union of two vectors

I have two arrays, as follows:

std::array<int,6> A,B;
//Fill A with random data
//File B with random data

For whatever reason, I'd like some kind of container object which lets me access both of the vectors individually, but also to iterate over their union, allowing for actions such as follows:

union_container uc(A,B);
for(unioned::iterator i=uc.begin();i!=uc.end();++i)
  *i+=1;
uc.first()[2]=4;
uc.second()[4]=5;

I could code this unioned class myself, but perhaps there is already a library which allows this?

Upvotes: 1

Views: 398

Answers (1)

TemplateRex
TemplateRex

Reputation: 70556

Using Boost zip iterators is one way to do this.

#include <array>
#include <functional>
#include <iostream>
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/zip_iterator.hpp>

template<typename T>
using ZipIt = boost::zip_iterator< boost::tuple<T*, T*> >;

template<typename T>
using ZipRef = decltype(*ZipIt<T>());

template<typename T>
void operator+=(ZipRef<T> z, T const& v)
{
    z.template get<0>() += v;
    z.template get<1>() += v;    
}

int main()
{
    std::array<int, 6> a = { 1, 3, 5, 7,  9, 11 };
    std::array<int, 6> b = { 2, 4, 6, 8, 10, 12 };

    std::for_each(
        boost::make_zip_iterator(boost::make_tuple(std::begin(a), std::begin(b))), 
        boost::make_zip_iterator(boost::make_tuple(std::end(a), std::end(b))), 
        [](ZipRef<int> z){ z += 1; }
    );

    std::copy(std::begin(a), std::end(a), std::ostream_iterator<int>(std::cout, ",")); std::cout << "\n";
    std::copy(std::begin(b), std::end(b), std::ostream_iterator<int>(std::cout, ",")); std::cout << "\n";

    a[2] = 4;
    b[4] = 5;
}

Online output.

Note that the code above is not as general as I've would liked, since the jump to variadic templates and general iterator types proved a bit hairy (left as an exercise!) This has mainly to do with the fact that boost::zip_iterator uses some tricky internal facades around boost::tuple. For this reason I also used decltype in the template alias for ZipRef to avoid having to write such nasty types inside the std::for_each lambda expression.

Upvotes: 1

Related Questions