Why does std::for_each(from, to, function) return function?

It's to allow you to accrue state in your function and then return it to your calling code. For instance, your function (as a functor class) could have a member int for counting the number of times it had been called.

Here is a page with some examples : https://web.archive.org/web/20171127171924/http://xenon.arcticus.com/c-morsels-std-for-each-functors-member-variables


It may be that Alex Stepanov had the functional programming paradigm, but you will find that both std::accumulate and std::for_each pass their operands around (the function and the accumulated value) by value, rather than by reference. Thus:

class MyFunctor
{
   Y val;
   public:
     MyFunctor() : val() {}

     void operator()( X const& x )
     {
        // do something to modify val based on x
     }

     Y getValue() const { return val; }   
};

Now if you try:

MyFunctor f;
for_each( coll.begin(), coll.end(), f );
Y y = f.getValue();

It won't work because for_each has been dealing with copies of f. Of course you could have an instance of shared_ptr<Y> internally which would therefore point to the same instance. You can also make val inside MyFunctor a reference, create it outside the loop and pass it in to MyFunctor.

However the language lets you just do:

Y y = for_each( coll.begin(), coll.end(), MyFunctor() ).getValue();

nice and convenient, all in one line.

To do the same with std::accumulate would be done like this:

class MyFunctor2
{
public:
      Y operator()( Y y, X const& x ) const
      {
         //    create a new Y based on the old one and x
        ...
      }
};

Y y = std::accumulate( coll.begin(), coll.end(), Y(), MyFunctor2() );

You could use a function (or in C++11 a lambda) instead of a functor. Note that the functor here has no state, and you pass in your initialised object as a parameter, which can be a temporary.

Now we know that Y is copyable. std::accumulate uses by value on Y, not an in-place modify. Incidentally when in-place modify really is more efficient, there is a workaround without writing a new algorithm (e.g. accumulate2 that uses += or reference modification) by using a function signature of:

Y * func( Y* py, X const & ); // function modifies *py in-place then returns py

then calling:

Y y;
std::accumulate( coll.begin(), coll.end(), &y, func );

We "know" the return value will be &y. We can make use of this if we want to access a member of Y in one place e.g.

Y y;
Z z = std::accumulate( coll.begin(), coll.end(), &y, func )->getZ();

Incidentally, a key difference to the copy in for_each and the copy in accumulate is the complexity / number of copies it will make. With for_each there will be at most 2 copies made of your functor: one as the parameter into the function and one in the return. I say "at most" because Return Value Optimisation could reduce the second of these copies. With accumulate it copies with every element in the collection, i.e O(N) rather than constant time. So if the copy is mildly expensive, the double copy in the functor will not be a major expense iterating a small number of times over large collections, whereas for accumulate it would be (and the suggestion would be the pointer hack).


If you pass in a function object, aka functor, and it has state, returning the function object allows you to access it's state after iterating the sequence. Let's say you had a function object that computes three different variables from the sequence and holds them in member variables. Each time the functor is called, you update the counters. If for_each didn't return the object, how would you get the result?

Note... this is why you must always implement copy-construction, and assignment for function objects with state.

Tags:

C++

Stl

Templates