【发布时间】:2020-04-04 15:21:35
【问题描述】:
Cppreference 有这个std::transform 的示例代码:
std::vector<std::size_t> ordinals;
std::transform(s.begin(), s.end(), std::back_inserter(ordinals),
[](unsigned char c) -> std::size_t { return c; });
但它也说:
std::transform不保证unary_op或binary_op的按顺序应用。要将函数按顺序应用于序列或应用修改序列元素的函数,请使用std::for_each。
这大概是为了允许并行实现。但是std::transform 的第三个参数是LegacyOutputIterator,它对++r 具有以下后置条件:
在此操作之后,
r不需要是可递增的,并且r的先前值的任何副本都不再需要是可取消引用或可递增的。
所以在我看来,输出的分配必须按顺序进行。它们是否只是意味着unary_op 的应用程序可能出现故障,并存储到临时位置,但按顺序复制到输出?这听起来不像是你想做的事情。
大多数 C++ 库实际上还没有实现并行执行器,但微软已经实现了。我很确定this 是相关代码,我认为它调用this populate() function 将迭代器记录到输出块中,这肯定不是一个有效的做法,因为@987654339 @ 可以通过增加它的副本来失效。
我错过了什么?
【问题讨论】:
-
godbolt 中的一个简单测试表明这是一个问题。使用 C++20 和
transform版本决定是否使用并行。大型向量的transform失败。 -
@Croolman 您的代码不正确,因为您正在回插入
s,这会使迭代器无效。 -
@DanielsaysreinstateMonica 哦,炸肉排你是对的。正在对其进行调整并使其处于无效状态。我收回我的评论。
-
有人闪回老问题是怎么回事?无论如何@DanielLangr 我的第一条评论代码是错误的,这就是你所指出的。当您在
godbolt中将back_inserter更改为插入到ordinals时,它会编译并且似乎可以工作。 -
@alfC
godbolt代码有一个问题,即在std::back_inserter中传入了s,而不是ordinals
标签: c++ stl language-lawyer c++17