具有多个容器的循环范围

oma*_*tai 14 c++ c++11

假设我有2个(或更多)容器我想同时迭代 - 例如,计算两个向量的点积:

std::vector<double> vector1;
std::vector<double> vector2;    // identical size to vector1
Run Code Online (Sandbox Code Playgroud)

同时在两个(或所有)容器上指定range-for循环的首选C++ 11方法是什么?是否涉及选择一个容器/迭代器来for ( auto i : c )在范围for for循环中编写short-hand(ie ),而所有其他容器/迭代器必须长期处理?是否有任何理由将来的语法无法扩展到支持两个/所有容器的短手,如下所示...这看起来真的可读:

double dotProduct( 0.0 );
for ( auto const & value1 : vector1, auto const & value2 : vector2 )  // illegal!
{
    dotProduct += value1*value2;
}
Run Code Online (Sandbox Code Playgroud)

Jen*_*ens 10

在其他(通常是功能性的)语言中,这是通过使用名为zip的函数来完成的.举个例子,Python有一个内置的zip,它遍历它的参数并返回一个元组:

for i in zip( [1,2,3], (1,2,3), { 0:0, 1:1, 2:2 } ): 
    l,t,d = i 
    print("list item: %d, tuple item %d, dict item %d" % (l,t,d) )      
Run Code Online (Sandbox Code Playgroud)

您可以在C++中使用范围库来获得该功能,例如Boost.RangeEric Niebler的rangev3.遗憾的是,Ranges没有在C++ 17标准中投票,但我绝不会在没有范围库的情况下启动项目.在Boost.Range中调用该函数combine:

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

int main(int, const char*[])
{
    using namespace boost;

    std::vector<int> const v{0,1,2,3,4};
    std::list<char> const  l{'a', 'b', 'c', 'd', 'e'};

    for(auto const& i: combine(v, l))
    {
        int ti;
        char tc;
        boost::tie(ti,tc) = i;
        std::cout << '(' << ti << ',' << tc << ')' << '\n';
    }

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

使用C++ 17,您可以替换std::tie带有结构化的绑定,并删除那种不寻常的"初始化" std::tie.

  for(auto const& [ti,tc] : boost::combine(v, l)) {
     std::cout << '(' << ti << ',' << tv << ')' << '\n';
  }
Run Code Online (Sandbox Code Playgroud)

虽然我很遗憾C++ 17中没有包含范围,但我认为结构化绑定是一个很大的进步,并将严重改变代码的编写方式.标准中的范围将使它们更受欢迎,并将它们从第三方库中提升,许多人都有反对意见,因为这是他们不了解C++程序员应该知道的标准功能.

  • 您可能会更新答案以指出刚刚采用的 for-C++17 结构化绑定将简化此过程:`for(auto const&amp; i : boost::combine(v, l)) { int ti; 字符tc;std::tie(ti,tc) = i; 使用(ti,tc);}` 改为 `for(auto const&amp; [ti,tc] : boost::combine(v, l)) { use(ti,tc); }`。我没有仔细研究过 `boost::combine` 但如果它与 `std::tie` 一起工作,那么它应该可以很好地处理结构化绑定。 (3认同)