for_each overconstrained?Section: 26.6.5 [alg.foreach] Status: C++11 Submitter: Alisdair Meredith Opened: 2009-04-29 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [alg.foreach].
View all other issues in [alg.foreach].
View all issues with C++11 status.
Discussion:
Quoting working paper for reference (26.6.5 [alg.foreach]):
template<InputIterator Iter, Callable<auto, Iter::reference> Function> requires CopyConstructible<Function> Function for_each(Iter first, Iter last, Function f);1 Effects: Applies f to the result of dereferencing every iterator in the range [first,last), starting from first and proceeding to last - 1.
2 Returns: f.
3 Complexity: Applies f exactly last - first times.
P2 implies the passed object f should be invoked at each stage, rather than
some copy of f. This is important if the return value is to usefully
accumulate changes. So the requirements are an object of type Function can
be passed-by-value, invoked multiple times, and then return by value. In
this case, MoveConstructible is sufficient. This would open support for
move-only functors, which might become important in concurrent code as you
can assume there are no other references (copies) of a move-only type and so
freely use them concurrently without additional locks.
[ See further discussion starting with c++std-lib-23686. ]
[ Batavia (2009-05): ]
Pete suggests we may want to look at this in a broader context involving other algorithms. We should also consider the implications of parallelism.
Move to Open, and recommend the issue be deferred until after the next Committee Draft is issued.
[ 2009-10-14 Daniel de-conceptified the proposed resolution. ]
The note in 26.1 [algorithms.general]/9 already says the right thing:
Unless otherwise specified, algorithms that take function objects as arguments are permitted to copy those function objects freely.
So we only need to ensure that the wording for
for_eachis sufficiently clear, which is the intend of the following rewording.
[ 2009-10-15 Daniel proposes: ]
Add a new Requires clause just after the prototype declaration (26.6.5 [alg.foreach]):
Requires:
Functionshall beMoveConstructible( [moveconstructible]),CopyConstructibleis not required.Change 26.6.5 [alg.foreach]/2 as indicated:
Returns: std::move(f).
[ 2009-10 post-Santa Cruz: ]
Move to Tentatively Ready, using Daniel's wording without the portion saying "CopyConstructible is not required".
[ 2009-10-27 Daniel adds: ]
I see that during the Santa Cruz meeting the originally proposed addition
,
CopyConstructibleis not required.was removed. I don't think that this removal was a good idea. The combination of 26.1 [algorithms.general] p.9
[Note: Unless otherwise specified, algorithms that take function objects as arguments are permitted to copy those function objects freely.[..]
with the fact that
CopyConstructibleis a refinementMoveConstructiblemakes it necessary that such an explicit statement is given. Even the existence of the usage ofstd::movein the Returns clause doesn't help much, because this would still be well-formed for aCopyConstructiblewithout move constructor. Let me add that the originally proposed addition reflects current practice in the standard, e.g. 26.7.9 [alg.unique] p.5 usages a similar terminology.For similar wording need in case for auto_ptr see 973.
[ Howard: Moved from Tentatively Ready to Open. ]
[
2009-11-20 Howard restores "not CopyConstructible" to the spec.
]
[ 2009-11-22 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
Proposed resolution:
Add a new Requires clause just after the prototype declaration (26.6.5 [alg.foreach]):
Requires:
Functionshall meet the requirements ofMoveConstructible( [moveconstructible]).Functionneed not meet the requirements ofCopyConstructible( [copyconstructible]).
Change 26.6.5 [alg.foreach]/2 as indicated:
Returns: std::move(f).