如何按顺序迭代几个容器



具有与以下内容类似的代码段:

#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
  }
}

我想一次性迭代v1v2中的所有元素(由于这些循环中的逻辑有点困难,因此我不能在其中使用函数 - 为了这个问题)。

因此,理想的解决方案是:

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

显然,没有分配所有元素复制到其中的新容器(因为该解决方案是微不足道的。

有没有类似的东西,例如在boost

使用 range-v3,您可以这样做

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;   
}

演示

下面是使用高阶函数的解决方案:

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);
}

您可以按如下方式使用forJoined

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".

如您所见forJoined当您的容器存储不同类型的元素时,它也可以工作。使用模板参数传递f不会带来额外的开销(请参阅我关于该主题的最新文章)。

您可以使用可变参数模板将其扩展到任意数量的容器。

可以使用初始值设定项列表。例如

#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;
}

程序输出为

A B C X Y Z 

最新更新