This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.

### 1110. Is `for_each` overconstrained?

Section: 25.6.4 [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 (25.6.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 25.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 (25.6.4 [alg.foreach]):

>   > Requires: `Function` shall be `MoveConstructible` ( [moveconstructible]), `CopyConstructible` is not required.

> - Change 25.6.4 [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 25.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. 25.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 (25.6.4 [alg.foreach]):

  > Requires: `Function` shall meet the requirements of `MoveConstructible` ( [moveconstructible]). `Function` need not meet the requirements of `CopyConstructible` ( [copyconstructible]).

- Change 25.6.4 [alg.foreach]/2 as indicated:

  > Returns: std::move(f).