多容器循环范围 [英] Range for loop with multiple containers

查看:79
本文介绍了多容器循环范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose I have 2 (or more) containers I want to iterate through simultaneously - for example, to compute the dot product of two vectors:

std::vector<double> vector1;
std::vector<double> vector2;    // identical size to vector1

为范围指定范围的首选C ++ 11方法是什么同时遍历两个(或所有)容器?是否涉及选择一个容器/迭代器在range-for循环中编写速记(即 for(auto i:c)),而所有其他容器/迭代器都有需要长期处理?出于下面的原因,是否有任何原因将来的语法无法扩展以支持两个/所有容器的简写……这似乎很可读:

What is the preferred C++11 way to specify a range-for loop over both (or all) containers simultaneously? Does it involve choosing one container/iterator to write short-hand (i.e. for ( auto i : c )) in a range-for loop, while all other containers/iterators have to be handled long-hand? Is there any reason the syntax in future could not be extended to support short-hand for both/all containers as shown below... which seems really readable:

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


推荐答案

其他(通常是功能)语言是通过使用称为zip的函数来完成的。例如,Python有一个内置的zip,它遍历其参数并返回一个元组:

In other (often functional) languages this is done by using a function called zip. As an example, Python has a builtin zip that iterates over over its arguments and returns a tuple:

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

您可以使用C ++中的范围库来获得该功能,例如 Boost.Range Eric Niebler的rangev3 。不幸的是,范围没有在C ++ 17标准中投票通过,但是我永远不会在没有范围库的情况下启动项目。在Boost.Range中,该函数称为 combine

You can use a range library in C++ to get that functionality, e.g. Boost.Range or Eric Niebler's rangev3. Ranges were unfortunately not voted in the C++17 standard, but I would never start a project without a range library. In Boost.Range the function is called 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;
}

使用C ++ 17可以替换 std :: tie 具有结构化绑定,并使用 std :: tie 删除异常的初始化。

With C++17 you can replace the std::tie with structured binding and remove the kind of unusual "initialization" with std::tie.

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

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

While I regret that ranges are not included in C++17, I think that structured bindings are a great advancement and will seriously change the way code is written. Having ranges in the standard would make them more popular and elevate them from a third-party library where many people have objections because it is something they don't know to a standard feature that C++ programmer ought to know.

这篇关于多容器循环范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆