3

Having similar piece of code to the following:

#include <iostream>
#include <vector>

int main()
{
  std::vector<std::string> v1, v2;
  for (const auto& s : v1) {
    // do something with s
  }
  for (const auto& s : v2) {
    // do something with s
  }
}

I would like to iterate over all elements from v1 and v2 in one go (and since the logic is kind of difficult in those loops I cannot use functions inside them - for the sake of this question).

So the ideal solution would be something like:

  for (const auto& s : magic(v1,v2)) {
    // do something with s
  }

obviously without allocating new container with all elements copied to it (since that solution is trivial.

Is there anything like it e.g. in boost?

Patryk
  • 22,602
  • 44
  • 128
  • 244

3 Answers3

2

With range-v3, you may do

const std::vector<std::string> v1{"A", "B", "C"}, v2{"D", "E", "F"};

for (const auto& s : ranges::view::concat(v1, v2)) {
    std::cout << s << std::endl;   
}

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
1

Here's a solution that uses an higher-order function:

template <typename TC0, typename TC1, typename TF>
void forJoined(TC0&& c0, TC1&& c1, TF&& f)
{
    for(auto&& x : c0) f(x);
    for(auto&& x : c1) f(x);
}

You can use forJoined as follows:

std::vector<int> a{0, 1, 2};
std::vector<char> b{'a', 'b', 'c'};

forJoined(a, b, [](auto x){ std::cout << x; });
// Will print "012abc".

As you can see forJoined will also work when your containers are storing elements of different types. Using a template parameter to pass f introduces no extra overhead (see my latest article on the subject).

You can extend this to an arbitrary number of containers by using a variadic template.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
0

You can use an initializer list. For example

#include <iostream>
#include <vector>
#include <string>
#include <functional>
#include <initializer_list>
#include <functional>

int main() 
{
    std::vector<std::string> v1 = { "A", "B", "C" };
    std::vector<std::string> v2 = { "X", "Y", "Z" };

    for ( const auto &r : { std::cref( v1 ), std::cref( v2 ) } )
    {
        for ( const auto &s : r.get() ) std::cout << s << ' ';
    }

    std::cout << std::endl;

    return 0;
}

The program output is

A B C X Y Z 
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335