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 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_each
is 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:
Function
shall beMoveConstructible
( [moveconstructible]),CopyConstructible
is 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
,
CopyConstructible
is 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
CopyConstructible
is a refinementMoveConstructible
makes it necessary that such an explicit statement is given. Even the existence of the usage ofstd::move
in the Returns clause doesn't help much, because this would still be well-formed for aCopyConstructible
without 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:
Function
shall meet the requirements ofMoveConstructible
( [moveconstructible]).Function
need not meet the requirements ofCopyConstructible
( [copyconstructible]).
Change 26.6.5 [alg.foreach]/2 as indicated:
Returns: std::move(f).