Search code examples
c++loopsstliterationauto

How can I use multiple containers in a range-based for?


I've got multiple containers of different types.
I'd like to perform the same action on all of the elements across all the containers.
Normally, this involves multiple range-based for loops with duplicated code:

#include <iostream>
#include <vector>
#include <set>

int main() {

    //containers
    std::vector<int> v1{1,2,3,4,5};
    std::set<float> v2{6,7,8,9,10};

    //perform iterations
    for (auto & it: v1){
        std::cout << it << ' ';
    }
    for (auto & it: v2){
        std::cout << it << ' ';
    }
}

I'd like to be able to do this instead,
by providing multiple containers to the same range-based for loop.

This of course does not work:

for (auto & it: v1,v2){
    std::cout << it << ' ';
}

Is there a library solution I could use to achieve this?


Solution

  • You could use boost range's combine:

    for(auto&& el : boost::combine(v1, v2)) {
        std::cout << boost::get<0>(el) << ", " << boost::get<1>(el) << '\n';
    }
    

    demo

    Or, range-v3's zip view:

    for(auto&& el : view::zip(v1, v2)) {
        std::cout << std::get<0>(el) << ", " << std::get<1>(el) << '\n';
    }
    

    demo


    Alternatively, you could make a range from zip iterators the hard way:

    auto b = boost::make_zip_iterator(boost::make_tuple(v1.begin(), v2.begin()));
    auto e = boost::make_zip_iterator(boost::make_tuple(v1.end(), v2.end()));
    for(auto&& tup : boost::make_iterator_range(b, e)) {
        std::cout << boost::get<0>(tup) << ", " << boost::get<1>(tup) << '\n';
    }
    

    demo