1110. Is for_each overconstrained?

Section: 28.5.4 [alg.foreach] Status: C++11 Submitter: Alisdair Meredith Opened: 2009-04-29 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [alg.foreach].

View all issues with C++11 status.

Discussion:

Quoting working paper for reference (28.5.4 [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 28.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: ]

[ 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 28.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 refinement MoveConstructible makes it necessary that such an explicit statement is given. Even the existence of the usage of std::move in the Returns clause doesn't help much, because this would still be well-formed for a CopyConstructible without move constructor. Let me add that the originally proposed addition reflects current practice in the standard, e.g. 28.6.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: