return sumSoFar + s.size();
}
Тело функции убеждает в том, что происходящее весьма тривиально, но на первый взгляд смущают объявления string::size_type
. На самом деле в них нет ничего страшного. У каждого стандартного контейнера STL имеется определение типа size_type, относящееся к счетному типу данного контейнера. В частности, значение этого типа возвращается функцией size. Для всех стандартных контейнеров определение size_type должно совпадать с size_t, хотя теоретически нестандартные STL-совместимые контейнеры могут использовать в size_type другой тип (хотя я не представляю, для чего это может понадобиться). Для стандартных контейнеров запись
Функция stringLenghSum является типичным представителем обобщающих функций, используемых при вызове accumulate. Функция получает текущее значение суммы и следующий элемент интервала, а возвращает новое значение накапливаемой суммы. Накапливаемая сумма (сумма длин строк, встречавшихся ранее) относится к типу string::size_type, а обрабатываемый элемент относится к типу string. Как это часто бывает, возвращаемое значение относится к тому же типу, что и первый параметр функции.
Функция stringLenghSum используется в сочетании с accumulate следующим образом:
set
// и заполнить его данными
string::size_type lengthSum =// Присвоить lengthSum
accumulate(ss.begin(),ss.end(), // результат вызова stringLengthSum 0,stringLengthSum); // для каждого элемента ss
// с нулевым начальным значением
Изящно, не правда ли? Произведение вычисляется еще проще, поскольку вместо написания собственной функции суммирования можно обойтись стандартным функтором multiplies:
vector
// и заполнить его данными
float product =// Присвоить product результат
accumulate(vf.begin(),vf.end(), // вызова multiplies
1.0,multples
// с начальным значением 1.0
Только не забудьте о том, что начальное значение вместо нуля должно быть равно единице (в вещественном формате, не в int!). Если начальное значение равно нулю, то результат всегда будет равен нулю — ноль, умноженный на любое число, остается нулем.
Последний пример не столь тривиален. В нем вычисляется среднее арифметическое по интервалу точек, представленных структурами следующего вида:
struct Point {
Point(double initX. double initY):x(initX),y(initY){};
double x.y;
};
В этом примере обобщающей функцией будет функтор PointAverage, но перед рассмотрением класса этого функтора стоит рассмотреть его использование при вызове accumulate:
list
Point avg=
accumulate(lp.begin(),lp.end(),
Point(0,0),
PointAverage());
// Вычисление среднего
// арифметического по точкам,
// входящим в список lр
Просто и бесхитростно, как и должно быть. На этот раз в качестве начального значения используется объект Point, соответствующий началу координат, а нам остается лишь помнить о необходимости исключения этой точки из вычислений.
Функтор PointAverage отслеживает количество обработанных точек, а также суммы их компонентов х и у. При каждом вызове он обновляет данные и возвращает средние координаты по обработанным точкам. Поскольку для каждой точки в интервале функтор вызывается ровно один раз, он делит суммы по составляющим х и у на количество точек в интервале. Начальная точка, переданная при вызове accumulate, игнорируется.
class PointAverage:
publiс binary_function
PointAverage():xSum(0),ySum(0),numPoints(0) {}
const Point operator() (const Point& avgSoFar, const Point& p)
++numPoints;
xSum += p.x;
ySum += p.y;
return Point(xSum/numPoints,ySum/numPoints);
}
private:
size_t numPoints;
double xSum;
double ySum;