0

我想使用迭代器遍历两个集合,根据涉及另一个的(足够复杂的)算法修改一个。考虑以下最小示例:

#include <iostream>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/range/combine.hpp>
#include <boost/tuple/tuple.hpp> // tie
using namespace std;
using namespace boost;

int main(void) {
  // input data; never mind how these get filled
  int aa[] = {2, 3, 5, 8, 13, 21};
  int bb[] = {1, 0, 1, 1,  0,  1};
  vector<int> a (&aa[0], &aa[sizeof(aa)/sizeof(aa[0])]);
  vector<int> b (&bb[0], &bb[sizeof(bb)/sizeof(bb[0])]);

  // output storage; assume it has always correct dim.
  vector<int> c (a.size());

  // iterate through two coll., reading from both
  int p, q;
  BOOST_FOREACH (tie(p,q), combine(a,b)) { // loop1
    cout << p << "*" << q << "=" << p*q << endl;
  }

  // iterate through one coll., writing to it
  BOOST_FOREACH (int& r, c) { // loop2
    r = 42;
  }

  // iterate through two coll., reading from one, writing to the other?
  BOOST_FOREACH (??? p, s ???, combine(a,c)) { // loop3
    s = p * 2;
  }

  return 0;
}

如何声明???s 之间的部分(或以其他方式更改 loop3 中的参数)?

4

2 回答 2

1

a 的值类型zip_range是对元素的引用元组:

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

int main(int ac,char* av[])
{
  // input data; never mind how these get filled
  int aa[] = {2, 3, 5, 8, 13, 21};
  int bb[] = {1, 0, 1, 1,  0,  1};
  std::vector<int> a(boost::begin(aa), boost::end(aa));
  std::vector<int> const b(boost::begin(bb), boost::end(bb));

  // output storage; assume it has always correct dim.
  std::vector<int> c (a.size());

  typedef boost::tuple<int const&, int&> val_t;
  BOOST_FOREACH(val_t const& v, boost::combine(a, c)) {
    v.get<1>() = v.get<0>() * 2;
  }
}
于 2013-05-22T23:55:38.830 回答
0

IMO,你过度使用BOOST_FOREACH到了几乎令人震惊的程度。就像std::foreach,这应该是您最后选择的算法之一。

您的第三个循环几乎肯定应该使用std::transform. 它的目的是获取一个输入范围,对其进行转换,然后将结果存储在一个输出范围中(或者获取两个输入范围,将它们组合起来,然后将结果放在第三个范围内,例如在您第一次(错误)使用 BOOST_FOREACH 时)。

使用它,您的第三个循环会出现如下内容:

// c[i] = a[i] * 2, i = 0..N-1
std::transform(begin(a), end(a), begin(c), [](int i) { return i * 2; });

至于你的第二个,看起来你真的很想要std::fill_n

std::fill_n(begin(c), end(c), 42);

现在,基于范围的东西(例如, Boost Range中的算法)确实可以通过用begin(X), end(X)单个参数替换每一对来使这变得更简单一些。尽管如此,这些已经明显优于带有杂项ties 和combines 的 BOOST_FOREACH 版本,以尝试将您的方形钉钉入圆孔。

于 2013-05-22T23:19:39.390 回答