475. May the function object passed to for_each modify the elements of the iterated sequence?

Section: 28.5.4 [alg.foreach] Status: CD1 Submitter: Stephan T. Lavavej, Jaakko Jarvi Opened: 2004-07-09 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [alg.foreach].

View all issues with CD1 status.

Discussion:

It is not clear whether the function object passed to for_each is allowed to modify the elements of the sequence being iterated over.

for_each is classified without explanation in [lib.alg.nonmodifying], "25.1 Non-modifying sequence operations". 'Non-modifying sequence operation' is never defined.

25(5) says: "If an algorithm's Effects section says that a value pointed to by any iterator passed as an argument is modified, then that algorithm has an additional type requirement: The type of that argument shall satisfy the requirements of a mutable iterator (24.1)."

for_each's Effects section does not mention whether arguments can be modified:

"Effects: Applies f to the result of dereferencing every iterator in the range [first, last), starting from first and proceeding to last - 1."

Every other algorithm in [lib.alg.nonmodifying] is "really" non-modifying in the sense that neither the algorithms themselves nor the function objects passed to the algorithms may modify the sequences or elements in any way. This DR affects only for_each.

We suspect that for_each's classification in "non-modifying sequence operations" means that the algorithm itself does not inherently modify the sequence or the elements in the sequence, but that the function object passed to it may modify the elements it operates on.

The original STL document by Stepanov and Lee explicitly prohibited the function object from modifying its argument. The "obvious" implementation of for_each found in several standard library implementations, however, does not impose this restriction. As a result, we suspect that the use of for_each with function objects that modify their arguments is wide-spread. If the restriction was reinstated, all such code would become non-conforming. Further, none of the other algorithms in the Standard could serve the purpose of for_each (transform does not guarantee the order in which its function object is called).

We suggest that the standard be clarified to explicitly allow the function object passed to for_each modify its argument.

Proposed resolution:

Add a nonnormative note to the Effects in 28.5.4 [alg.foreach]: If the type of 'first' satisfies the requirements of a mutable iterator, 'f' may apply nonconstant functions through the dereferenced iterators passed to it.

Rationale:

The LWG believes that nothing in the standard prohibits function objects that modify the sequence elements. The problem is that for_each is in a secion entitled "nonmutating algorithms", and the title may be confusing. A nonnormative note should clarify that.