C++ 我可以将std::transform与并行执行策略一起使用吗?

C++ 我可以将std::transform与并行执行策略一起使用吗?,c++,parallel-processing,stl,c++17,C++,Parallel Processing,Stl,C++17,如果我没有弄错的话,我可以使用与输入和输出迭代器相同的范围使std::transform就地执行。假设我有一些std::vector对象vec,那么我会写 std::transform(vec.cbegin(),vec.cend(),vec.begin(),unary_op) 使用合适的一元操作一元操作 使用C++17标准,我希望通过在其中粘贴一个std::execution::par作为第一个参数来并行执行转换。这将使函数在中从重载(1)变为重载(2)。然而,对这一过载的评论说: unary

如果我没有弄错的话,我可以使用与输入和输出迭代器相同的范围使
std::transform
就地执行。假设我有一些
std::vector
对象
vec
,那么我会写

std::transform(vec.cbegin(),vec.cend(),vec.begin(),unary_op)
使用合适的一元操作
一元操作

使用C++17标准,我希望通过在其中粘贴一个
std::execution::par
作为第一个参数来并行执行转换。这将使函数在中从重载(1)变为重载(2)。然而,对这一过载的评论说:

unary_op
[…]不得使任何迭代器(包括结束迭代器)无效,或修改所涉及范围的任何元素。(从C++11开始)


“修改任何元素”是否真的意味着我不能在适当的位置使用算法,或者这是指我误解的不同细节?

我相信这是指不同的细节。
一元运算
获取序列的一个元素并返回一个值。该值存储(通过
转换
)到目标序列中

所以这个
一元运算
就可以了:

int times2(int v) { return 2*v; }
但这一条不会:

int times2(int &v) { return v*=2; }
但这不是你真正想问的。
您想知道是否可以使用
transform
uniary_op
版本作为具有相同源和目标范围的并行算法。我不明白为什么不<代码>转换
将源序列的单个元素映射到目标序列的单个元素。但是,如果您的
uniary\u op
不是真正的一元(即,它引用序列中的其他元素-即使它只读取它们,那么您将有一个数据竞争)。

正如您在引用的链接示例中所看到的,修改任何元素并不意味着对元素进行所有类型的修改:

函数的签名应等同于以下内容:

Ret fun(const Type &a);
这包括对元素的修改。在最坏的情况下,如果您使用相同的迭代器作为目标,修改不应导致迭代器无效,例如
向后推
到向量或
向量
删除可能导致迭代器无效的迭代器


请参阅一个不应执行的故障示例。

此处引用标准

[alg.transform.1]

op[…]不得使迭代器或子范围无效,或修改 范围

这将禁止您的
一元操作
修改作为参数给出的值或容器本身

auto unary_op = [](auto& value) 
{ 
    value = 10;    // this is bad
    return value;
}

auto unary_op = [&vec](auto const& value) 
{ 
    vec[0] = value;   // also bad
    return value;
}

auto unary_op = [&vec](auto& value) 
{ 
    vec.erase(vec.begin());   // nope 
    return value;
}
但是,下面的代码是可以的

auto unary_op = [](auto& value)  // const/ref not strictly needed
{         
    return value + 10;   // totally fine
}

auto unary_op = [&vec](auto& value)
{         
    return value + vec[0];   // ok in sequential but not in parallel execution
}
独立于
一元操作
我们有

[alg.transform.5]

在一元变换的情况下,结果可能等于第一个[…]

意味着明确允许就地操作

现在

[算法.并行.重载.2]

除非另有规定,否则ExecutionPolicy算法重载的语义与它们的重载相同,而不包含

表示执行策略在算法上没有用户可见的差异。您可以期望算法产生完全相同的结果,就像您不指定执行策略一样