迭代多个seq.C++中的容器11

Exc*_*bur 12 c++ iterator c++11

我需要一个针对以下情况的建议 - 我几个小时都无法弄明白:如何通过多个seq.容器大小相同(这里:两个向量)的简单方法?

int main() {
  int size = 3;
  std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };

  // old-fashioned - ok
  for (int i = 0; i < size; i++) {
    std::cout << v1[i] << " " << v2[i] << std::endl;
  }

  // would like to do the same as above with auto range-for loop
  // something like this - which would be fine for ONE vector.
  // But this does not work. Do I need a hand-made iterator instead?
  for (const auto& i:v1,v2) {
    std::cout << i << " " << i << std::endl;
  }

  return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

Tem*_*Rex 15

boost::combine()Boost.Range允许一个写

#include <iostream>
#include <iterator>
#include <vector>
#include <boost/range/combine.hpp>

int main()
{
    std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };

    for (auto&& t : boost::combine(v1, v2))
            std::cout << t.get<0>() << " " << t.get<1>() << "\n";    
}
Run Code Online (Sandbox Code Playgroud)

实例.

如果你不喜欢依靠这一点,你可以拼出combine()自己与功能Boost.Iteratorzip_iteratorBoost.Rangeiterator_range和C++ 14推导返回类型一点点:

template<class... Ranges>
auto combine(Ranges const&... ranges) 
// add -> decltype( boost::make_iterator_range(...) ) in C++11
{
    return boost::make_iterator_range(
        boost::make_zip_iterator(boost::make_tuple(begin(ranges)...)),
        boost::make_zip_iterator(boost::make_tuple(end(ranges)...))        
    );
}
Run Code Online (Sandbox Code Playgroud)

实例.

说明:在输入范围中boost::make_zip_iterator创建一个boost::tuple迭代器,并从常规迭代器中重载所有常用的operator++以及operator*您熟悉和喜爱的内容.所述iterator_range然后包装两种这些的zip_iterators转换与一个包begin()end()功能,允许它由C++ 11范围-for循环中使用.它也推广到两个以上的输入范围.您可以K使用.get<K>成员函数从元组中解压缩-th元素.

  • 啊,Boost ......自1999年以来"简化"你的代码:-) (2认同)
  • 好吧,我看到了优点,拉链迭代器(或范围)是真正应该存在的非常基础的东西.我只是希望你能拼写它像`begin(v1,v2)`左右...... (2认同)
  • @KerrekSB:实际上,我希望我能说'for(auto && t:zip(v1,v2))`; `zip`在所有函数式语言中都是众所周知的.当然,真正的问题是我们在C++中没有元组解包(因为元组是库特性,而不是语言特性)所以可用性`get <0>(t)`对于计数来说有点下降.然而,在设计"zip"方法时存在一个重要问题:如何处理不同长度的序列?而且我不知道Boost如何处理这种情况(典型的选择是:最短的停止,带有一些给定元素的pad,带有null的pad). (2认同)
  • @TemplateRex:太棒了!我用不等长度的输入检查了行为并且它是一个混合包:[它计算距离](http://coliru.stacked-crooked.com/a/1a5c6653d020f874)以防止第二个序列比第一个短,但反过来[它不那么好](http://coliru.stacked-crooked.com/a/cccc08dba54735f1). (2认同)

Rei*_*ica 14

基于范围的for循环被设计为迭代一个范围的便利,因为它是迄今为止最常见的情况.如果您需要迭代多个范围(这不是最常见的情况),您仍然可以采用传统方式:

for (auto i1 = begin(v1), i2 = begin(v2), e = end(v1); i1 != e; ++i1, ++i2)
{
  // processing
}
Run Code Online (Sandbox Code Playgroud)

  • 不应该是`e1 = end(v1),e2 = end(v2); i1!= e1 && i2!= e2`?我意识到在这种情况下,两个向量碰巧具有相同的长度,但是`for`循环是否应该依赖于它? (3认同)
  • +1 ...不是所有东西都需要被扼杀到一个特定的语言特征中.C++的发展特别强调了可以很好地协同工作的有用功能; 一个新功能不会驱逐另一个功能,但它们都会使语言变得更好. (2认同)
  • @DavidConrad OP在问题中陈述了"不止一个相同大小的seq.容器",所以我相应地说明了答案.在一般情况下,有多种方法可以解决这个问题 - 将相同长度作为前提条件,以最短时间终止,提前测试,...... (2认同)