I'm looking for the recommended way to convert a concurrent_vector
from the PPL library to a normal std::vector.
I have a function which returns its results in a std::vector
but may or may not use parallel algorithms internally. Currently I'm using insert
to copy the elements from the concurrent vector to the normal vector:
#ifdef PARALLEL
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in a parallel algorithm
std::vector<Foo> sv;
sv.insert(sv.begin(), cv.begin(), cv.end());
return sv;
}
#else
std::vector<Foo> Bar() {
std::vector<Foo> sv;
//Fill sv in a sequential algorithm
return sv;
}
#endif
Although the performance of the insert operation is not a real issu at the moment (compared to the function body), it just seems unnecessary and I wonder whether there is a better solution (Btw.: Foo
is a simple POD which cannot be moved).
Ideally I would like to have something similar to this
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in a parallel algorithm
return static_cast<std::vector<Foo>>(cv);
}
or at least
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in a parallel algorithm
std::vector<Foo> sv(std::move(cv));
return sv;
}
Are there any suggestions on how to do this properly?
EDIT:
As always I overlooked the most obvious simplification (suggested by Chris):
std::vector<Foo> Bar() {
concurrency::concurrent_vector<Foo> cv;
//Fill cv in a parallel algorithm
return std::vector<Foo>(cv.begin(), cv.end());
}
while it (most probably) doesn't get rid of the copies it looks much cleaner.
EDIT2:
This leads me to the qestion of - assuming there is no way to explicitly prevent a copy of the vector data - how likely it is that the compiler can optimize the copy (from concurrent to std::vector) away, while still applying RVO
or a move operation on the functions' return value
insert
. Use the constructor. – Dissemblereturn {cv.begin(), cv.end()};
but I don't think there's any way other than copying. – Valerievalerioreturn {std::make_move_iterator(cv.begin()), std::make_move_iterator(cv.end())};
, although it obviously makes no difference if move is equivalent to copy forFoo
. – PanatellaFoo
is moveable. – Valerievalerio