for_each_acc: A new algorithm aka for_each() on steroids


My current work frequently revolves around creating a predicate which iterates over a list of objects, applies a predicate on each and returns the combined result of the operations. Even with much racking of the ol’ gray matter, I couldn’t really figure out how to do this with std::for_each or std::accumulate as-is. The new algorithm is a combination of std::for_each and/or std::accumulate. And I wasn’t really going to pull-in boost lambda for this one simple thing.

It was time to roll my own algorithm!

I start with a boolean value (typically true) and then keep combining the result of applying a given predicate f on an iterator range and keep updating this initial value. The update is typically done by using std::logical_and<bool>. But of course, I leave it to the client to specify what exact boolean operator to use (though anything beyond std::logical_or and std::logical_or is perhaps a bit too exotic for my taste!).

For the curious here goes the source: Happy digging!

/*
Requires: Function and LogicalOp shall meet the requirements of CopyConstructible.
     T shall meet the requirements of CopyConstructible and Assignable.
Effects: Computes its result by initializing the accumulator acc with the initial
     value init and then modifies it with acc = op(f(*b), acc) where op is a
     logical operator (such as `and', `not' etc.). The first argument to op
     is the result of dereferencing every iterator in the range [first, last)
     and applying f, starting from first and proceeding to last - 1. Note
     that the f(*b) being the first parameter ensures that an application of f
     is missed due to short-circuiting.
Returns: The accumulator value.
Complexity: Applies f and op exactly last - first times.
Remarks: Returns a result of type T
*/
template LogicalOp>
T for_each_acc(InIt b, InIt e, Function f, T init, LogicalOp op) {
     for (; b != e; ++b) {
          init = op(f(*b), init);
}
return init;
}

Advertisements

About this entry