多容器循环范围 [英] Range for loop with multiple containers
问题描述
假设我有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屋!