How to iterate over two containers sequentially

A simple solution is to use a helper function:

#include <functional>

template <typename Func, typename... Containers>
void for_all(Func&& func, Containers&&... containers) {
    auto iteration_func = [&](auto&& container) {
        for (auto&& elem : std::forward<decltype(container)>(container)) {
            std::invoke(func, std::forward<decltype(elem)>(elem));
        }
    };

    (iteration_func(std::forward<Containers>(containers)), ...);
}

Here, we use a fold expression with an immediately invoked lambda to simulate a loop over the variadic template arguments, where each of them is looped over and the provided function object is invoked on its elements.

The use of forwarding references and invocations to std::forward preserve the value categories of arguments and elements, for compatibility with rvalue ranges (e.g., move_view from the range-v3 library). std::invoke generalizes the notion of function objects to pointers to members, which can be useful in certain cases.

Example:

int main() {
    std::vector<int> vec_a{1, 2, 3};
    std::vector<int> vec_b{4, 5, 6, 7};
    
    for_all([](int n) {
        std::cout << n << ' ';
    }, vec_a, vec_b);
    
    std::cout << '\n';
}

(wandbox)

Different container types can be mixed:

for_all([](const auto& n) {
    std::cout << n << ' ';
}, std::vector{1, 2, 3}, std::list{"foo", "bar"});

Tags:

C++