我有一个const std::vector<T> source
大号的,还有一个std::vector<T> dest
。我想对 中的每个元素应用转换source
并将其存储在dest
; 所有这些都是并行的,并且知道这T
不是默认可构造的。
我最初尝试的是使用std::transform
并行执行策略:
std::transform(std::execution::par_unseq,
source.begin(), source.end(),
dest.begin(),
[](const T& elem) { return op(elem); }
);
Run Code Online (Sandbox Code Playgroud)
然而,当我第一次编译并运行它时,令我惊讶的是,我发现虽然transform
“循环”了很多source.size()
次,dest
但内容仍然没有改变。
我发现这是因为之前的dest
必须具有相同的大小。但是,我无法将大小调整为 的大小,因为它不能默认构造,因为它没有默认构造函数。我也不想为它提供默认构造函数(首先,它在的逻辑中没有意义,但您可以认为调用它会很昂贵)。source
transform
dest
source
T
T
C++ STL 是否提供任何其他算法来实现我的想法?
足够的算法是每个线程计算自己的向量部分source
,然后收集结果并将其连接到同一个dest
向量中。
尝试使用std::vector<>
of std::optional<T>
:
#include <algorithm>
#include <execution>
#include <optional>
#include <vector>
struct T { // NOTE: T is NOT default-constructible!
T(int x) : value(x) {}
operator int() { return value; }
int value;
};
T op(const T& in) {
return in.value * 2;
}
#include <iostream>
int main() {
const std::vector<T> source = {4, 5, 6, 7, 8, 9, 10, 11};
std::vector<std::optional<T>> dest(source.size());
std::transform(
std::execution::par_unseq,
source.begin(), source.end(),
dest.begin(),
[](const T& elem) { return op(elem); }
);
for (auto i : dest) {
std::cout << *i << " ";
}
std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
示例输出:8 10 12 14 16 18 20 22
Godbolt 演示: https: //godbolt.org/z/ecf95cneq
诚然,这不是那么惯用,因为您的dest
数组现在将每个元素都包装在一个std::optional<>
容器中,但我相信它以其他方式提供您指定的语义。