我想用BOOST FOREACH复制以下内容
std::vector<int>::const_iterator i1;
std::vector<int>::const_iterator i2;
for( i1 = v1.begin(), i2 = v2.begin();
i1 < v1.end() && i2 < v2.end();
++i1, ++i2 )
{
doSomething( *i1, *i2 );
}
答案 0 :(得分:33)
同时迭代两个东西称为“zip”(来自函数式编程)和Boost has a zip iterator:
zip迭代器提供并行迭代的功能 同时控制序列。构建了一个zip迭代器 来自迭代器的元组。移动zip迭代器会移动所有 并行的迭代器。取消引用zip迭代器会返回一个元组 它包含取消引用各个迭代器的结果。
请注意,它是一个迭代器,而不是范围,因此要使用BOOST_FOREACH
,您必须将其中两个填充到iterator_range或pair
中。所以它不会很漂亮,但是有点小心你可以想出一个简单的zip_range
并写一下:
BOOST_FOREACH(boost::tuple<int,int> &p, zip_range(v1, v2)) {
doSomething(p.get<0>(), p.get<1>());
}
或2的特殊情况并使用std::pair
而不是boost::tuple
。
我认为,由于doSomething
可能包含参数(int&, int&)
,实际上我们需要tuple<int&,int&>
。希望它有效。
答案 1 :(得分:16)
如果你使用boost,我认为它应该简单:
#include <boost/foreach.hpp>
#include <boost/range/combine.hpp>
std::vector<int> v1;
std::vector<int> v2;
// iterate over values
int i1, i2;
BOOST_FOREACH(boost::tie(i1, i2), boost::combine(v1, v2))
std::cout << i1+i2 << "\n"; // sums two vectors
// iterate over references
typedef boost::tuple<int&, int&> int_ref_tuple;
BOOST_FOREACH(int_ref_tuple tup, boost::combine(v1, v2))
tup.get<0>() = tup.get<1>(); // assigns one vector to another
奇怪的是,boost :: combine没有记录。无论如何,对我有用。
答案 2 :(得分:8)
如果你想使用BOOST_FOREACH
同时迭代两个向量,就像你在示例代码中所做的那样,那么你必须将两个向量封装在一个包装类中,该类应该公开begin
和end
功能。这些函数返回自定义迭代器,用于迭代包装器,内部将迭代两个向量。听起来不太好,但这就是你要做的事情。
这是我第一次尝试实现这一点( 最小化实现只是为了演示基本想法 ):
template<typename T>
struct wrapper
{
struct iterator
{
typedef typename std::vector<T>::iterator It;
It it1, it2;
iterator(It it1, It it2) : it1(it1), it2(it2) {}
iterator & operator++()
{
++it1; ++it2; return *this;
}
iterator & operator *()
{
return *this;
}
bool operator == (const iterator &other)
{
return !(*this != other);
}
bool operator != (const iterator &other)
{
return it1 != other.it1 && it2 != other.it2;
}
};
iterator begin_, end_;
wrapper(std::vector<T> &v1, std::vector<T> &v2)
: begin_(v1.begin(), v2.begin()),end_(v1.end(), v2.end())
{
}
wrapper(const wrapper & other) : begin_(other.begin_), end_(other.end_) {}
iterator begin()
{
return begin_;
}
iterator end()
{
return end_;
}
};
以下是测试代码。因为它使用了通常的for
循环,因为没有为C ++ 0x安装了ideone,或者在包含它时我做错了。
int main() {
std::vector<int> v1 = {1,2,3,4,5,6};
std::vector<int> v2 = {11,12,13,14,15};
wrapper<int> w(v1,v2);
for(wrapper<int>::iterator it = w.begin(); it != w.end(); ++it)
{
std::cout << *it.it1 <<", "<< *it.it2 << std::endl;
}
return 0;
}
输出:
1, 11
2, 12
3, 13
4, 14
5, 15
这仅适用于实验和学习目的,因为我并不认为它是完美的。可以有很多改进。 @Steve已经发布了boost的解决方案。
答案 3 :(得分:4)
感谢Steve Jessop的回答和出色的评论,我提出了以下解决方案,所以如果你发现这很好,请先回答Steve Jessop的回答。 ;)
#include <iostream>
#include <vector>
#include <boost/typeof/typeof.hpp>
#include <boost/typeof/std/vector.hpp>
#include <boost/foreach.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/range/iterator_range.hpp>
using namespace boost;
int main(int argc, char **argv) {
std::vector<int> vecFirst = assign::list_of(1)(2)(3)(43)(7)(13);
std::vector<double> vecSecond = assign::list_of(53.45)(-23.545)(0.1574)(1.001)(0.0047)(9.7);
BOOST_AUTO(zipSequence,
make_iterator_range(
make_zip_iterator(make_tuple(vecFirst.begin(), vecSecond.begin())),
make_zip_iterator(make_tuple(vecFirst.end(), vecSecond.end()))
)
);
BOOST_FOREACH( BOOST_TYPEOF(*zipSequence.begin()) each, zipSequence) {
std::cout << "First vector value : " << each.get<0>()
<< " - Second vector value : " << each.get<1>()
<< std::endl;
}
}