C ++ передает вектор unique_ptrs в качестве параметров соответствующему элементу другого вектора равной длины (особенно параллельно) - PullRequest
0 голосов
/ 08 декабря 2011

У меня есть:

  • вектор unique_ptr с ObjectA

  • вектор нового по умолчанию построенного вектора ObjectB, и

  • функция в объекте B, имеющая подпись void f(unique_ptr<ObjectA> o).

(слово Object здесь не указывается)

Как сделатьЯ делаю Bvec[i].f(Avec[i]) для всех 0 < i < length параллельно?

Я пытался использовать transform(Bvec.begin(), Bvec.end(), A.begin(), B.begin(), mem_fun_ref(&B::f)), но это дает кучу ошибок, и я не уверен, будет ли он даже передавать правильный A в качестве параметране говоря уже о том, чтобы позволить мне переместить их.(&B::f(A.begin()) не будет работать как последний параметр.

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

Я, конечно, могу использовать цикл for от 0 до конца, но я уверен, чтоесть простая вещь, которую я пропускаю, и она не параллельна простой петле for.

Спасибо.

1 Ответ

0 голосов
/ 08 декабря 2011

Вот непараллельная реализация, использующая алгоритм ручной работы. Я уверен, что кто-то более разбирающийся в functional может найти более элегантное решение. Проблема с transform заключается в том, что мы не можем использовать его с функциями, возвращающими void, и я не могу вспомнить другую функцию stdlib, которая принимает два диапазона и применяет их друг к другу. Если вы действительно хотите распараллелить это, это нужно сделать в функции apply_to. Запуск задачи async (например, std::async(*begin++, *begin2++) может сработать, хотя у меня нет такого опыта и я не могу заставить ее работать на gcc 4.6.2.

#include <iterator>
#include <memory>
#include <vector>
#include <algorithm>
#include <functional>


// this is very naive it should check call different versions
// depending on the value_type of iterator2, especially considering
// that a tuple would make sense
template<typename InputIterator1, typename InputIterator2>
void apply_to(InputIterator1 begin, InputIterator1 end, InputIterator2 begin2) {
  while(begin != end) {
    (*begin++)(*begin2++);
  }
}

struct Foo {

};

struct Bar {
  void f(std::unique_ptr<Foo>) { }
};


int main()
{
  std::vector< std::unique_ptr<Foo> > foos(10);
  std::vector< Bar > bars(10);
  std::vector< std::function<void(std::unique_ptr<Foo>) > > funs;

  std::transform(bars.begin(), bars.end(), std::back_inserter(funs),
                 // non-const due to f non-const, change accordingly
                 [](Bar& b) { return std::bind(&Bar::f, &b, std::placeholders::_1); });

  // now we just need to apply each element in foos with funs
  apply_to(funs.begin(), funs.end(), std::make_move_iterator(foos.begin()));


  return 0;
}
...