Parallel for_each iterators don't have to be mutable#3056
Conversation
The overloads of for_each that take an execution policy argument do not require that the iterator arguments always be mutable iterators. Whether or not the iterators need to be mutable depends on what the function object does. for_each is unusual, if not unique, in this regard; for all other algorithms the mutability of the iterators is specified by the algorithm. See http://eel.is/c++draft/alg.foreach#7 , though I admit that the wording is not particularly clear about this. Since the compiler can't realiably figure out whether or not the function object modifies the elements in the sequence, for_each should only check for constant iterators (_REQUIRE_PARALLEL_ITERATOR), not mutable iterators (_REQUIRE_CPP17_MUTABLE_ITERATOR). This bug was introduced by microsoft#2960 . That PR should not have changed for_each.
|
This is an important fix. My experience with C++ parallel algorithms is that it is very common to use For example: That test program requires this change to compile. (The output will be garbled and in a sort of random order due to the parallelism, but I was just looking for a very quick test case.) |
|
Thanks for this fix! (And noticing/fixing it so quickly, before STL changes stop flowing into VS 2022 17.4 Preview 3 - we should be able to prevent the bug from ever shipping to customers.) I remember thinking about this question while reviewing the PR (especially because LWG-475 "May the function object passed to |
|
Credit for finding the bug goes to Pili Latiesa. They contacted me as the author of P2408 to ask if |
|
I'm speculatively mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
CaseyCarter
left a comment
There was a problem hiding this comment.
LGTM. Thanks for the fix, and thanks to Pili for finding this.
|
Mmh, I'll note that this isn't a regression, however, this does fix a bug in implementing P2408R5. Thanks for noticing and the quick fix! |
|
Thanks again for fixing this, and congratulations on your first microsoft/STL commit! 😸 🎉 🚀 |
The overloads of
for_eachandfor_each_nthat take an execution policy argument do not require that the iterator arguments always be mutable iterators. Whether or not the iterators need to be mutable depends on what the function object does.for_eachandfor_each_nare unusual, if not unique, in this regard; for all other algorithms the mutability of the iterators is specified by the algorithm. See http://eel.is/c++draft/alg.foreach#7 , though I admit that the wording is not particularly clear about this.Since the compiler can't reliably figure out whether or not the function object modifies the elements in the sequence,
for_eachandfor_each_nshould only check for constant iterators (_REQUIRE_PARALLEL_ITERATOR), not mutable iterators (_REQUIRE_CPP17_MUTABLE_ITERATOR).This bug was introduced by #2960 . That PR should not have changed
for_eachorfor_each_n.