Easy way to iterate over two structures consecutively with a foreach loop

Viewed 171

Is there an easy way to achieve this design pattern in c++17?

std::set<uint32_t> first;
std::set<uint32_t> second;

for (uint32_t number : JoinIterator<uint32_t>(first, second)) {
   <DO SOMETHING WITH number>
}

This would replace the following code:

std::set<uint32_t> first;
std::set<uint32_t> second;

for (uint32_t number : first) {
   <DO SOMETHING WITH number>
}

for (uint32_t number : second) {
   <DO SOMETHING WITH number>
}

All of the search results I have found are about looping over both structures in parallel, not looping over the structures consecutively.

2 Answers

Use views::concat from range-v3:

for (uint32_t number : views::concat(first, second)) {
   <DO SOMETHING WITH number>
}

This only works with ranges that have the same underlying type (which is true in this example).


In Boost (i.e. range-v2), this is spelled boost::range::join(first, second).

Since it's not apparent from the Boost documentation directly, this function is found in boost/range/join.hpp

How about using for_each with boost?

#include<iostream>
#include <algorithm>
#include <set>
#include <boost/iterator/zip_iterator.hpp>

int main(){
    std::set<uint32_t> first = {1,2,3};
    std::set<uint32_t> second = {4,5,6};
    std::for_each(
        boost::make_zip_iterator(boost::make_tuple(first.begin(), second.begin())), 
        boost::make_zip_iterator(boost::make_tuple(first.end(),second.end())), 
        [](const boost::tuple<uint32_t,uint32_t>& t) {
            std::cout << t.get<0>() << " : " << t.get<1>() << std::endl;
        });
    return 0;
}

Not sure if it'll suit your needs but is pretty useful in some cases

Related