Search code examples
c++algorithmiteratorstl-algorithmistream-iterator

Run two <algorithm>s side by side on the same input iterator range


If I want to calculate the sum of a bunch of numbers retrieved from an std::istream, I can do the following:

// std::istream & is = ...
int total = std::accumulate(std::istream_iterator<int>(is),
                            std::istream_iterator<int>(),
                            0);

However, if I want to calculate their average, I need to accumulate two different results:

  • the total sum (std::accumulate)
  • the total count (std::distance)

Is there any way to "merge" these two algorithms and run them "side by side" in a single pass of an iterator range? I would like to do something like:

using std::placeholders;
int total, count;
std::tie(total, count) = merge_somehow(std::istream_iterator<int>(is),
                                       std::istream_iterator<int>(),
                                       std::bind(std::accumulate, _1, _2, 0),
                                       std::distance);
double average = (double)total / count;

Is this possible?


Solution

  • A ready-made solution for this sort of single-pass accumulation is implemented by Boost.Accumulators. You make a single accumulator, say for sum, count and average, populate it, and then extract all three results at the end.