Обратная запись в итератор при зацикливании более чем одной коллекции

Я хотел бы перебрать две коллекции с помощью итераторов, модифицируя одну на основе (достаточно сложного) алгоритма, включающего другую. Рассмотрим следующий минимальный пример:

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

0

Решение

Тип значения 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;
}
}
1

Другие решения

ИМО, ты злоупотребляешь 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);

Теперь, безусловно, верно, что что-то основано на диапазонах (например, алгоритмы в Диапазон увеличения) может сделать это немного проще, заменив каждый begin(X), end(X) пара с одним параметром. Тем не менее, они уже явно превосходят версии BOOST_FOREACH с разными tieс и combines, чтобы попытаться заставить ваши квадратные колышки в круглые отверстия.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector