将一个元素向量并行转换为另一个元素向量,无需初始化后者

ste*_*ddy 4 c++ stl

我有一个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必须具有相同的大小。但是,我无法将大小调整为 的大小,因为它不能默认构造,因为它没有默认构造函数。我也不想为它提供默认构造函数(首先,它在的逻辑中没有意义,但您可以认为调用它会很昂贵)。sourcetransformdestsourceTT

C++ STL 是否提供任何其他算法来实现我的想法?

足够的算法是每个线程计算自己的向量部分source,然后收集结果并将其连接到同一个dest向量中。

sax*_*one 6

尝试使用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<>容器中,但我相信它以其他方式提供您指定的语义。