Namespaces
Variants

std::accumulate

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, p.ej. ranges::copy, ranges::sort, ...
Operaciones de secuencia no modificadoras    
Operaciones por lotes
(C++17)
Operaciones de búsqueda
Operaciones de secuencia modificadoras
Operaciones de copia
(C++11)
(C++11)
Operaciones de intercambio
Operaciones de transformación
Operaciones de generación
Operaciones de eliminación
Operaciones de cambio de orden
(hasta C++17)(C++11)
(C++20)(C++20)
Operaciones de muestreo
(C++17)

Operaciones de ordenamiento y relacionadas
Operaciones de partición
(C++11)    

Operaciones de ordenamiento
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjuntos (en rangos ordenados)
Operaciones de fusión (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
(C++11)
(C++17)
Operaciones de comparación lexicográfica
Operaciones de permutación


 
 
Definido en el encabezado <numeric>
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
(1) (constexpr desde C++20)
template< class InputIt, class T, class BinaryOp >
T accumulate( InputIt first, InputIt last, T init, BinaryOp op );
(2) (constexpr desde C++20)

Calcula la suma del valor dado init y los elementos en el rango [first, last).

1) Inicializa el acumulador acc (de tipo T) con el valor inicial init y luego lo modifica con acc = acc + *i(hasta C++20)acc = std::move(acc) + *i(desde C++20) para cada iterador i en el rango [first, last) en orden.
2) Inicializa el acumulador acc (de tipo T) con el valor inicial init y luego lo modifica con acc = op(acc, *i)(hasta C++20)acc = op(std::move(acc), *i)(desde C++20) para cada iterador i en el rango [first, last) en orden.

Si cualquiera de las siguientes condiciones se cumple, el comportamiento no está definido:

  • T no es CopyConstructible.
  • T no es CopyAssignable.
  • op modifica cualquier elemento de [first, last).
  • op invalida cualquier iterador o subrango en [first, last].

Parámetros

first, last - el par de iteradores que define el rango de elementos a acumular
init - valor inicial de la acumulación
op - objeto función de operación binaria que se aplicará.

La firma de la función debe ser equivalente a la siguiente:

Ret fun(const Type1 &a, const Type2 &b);

La firma no necesita tener const &.
El tipo Type1 debe ser tal que un objeto de tipo T pueda convertirse implícitamente a Type1. El tipo Type2 debe ser tal que un objeto de tipo InputIt pueda ser desreferenciado y luego convertirse implícitamente a Type2. El tipo Ret debe ser tal que un objeto de tipo T pueda asignarse un valor de tipo Ret. ​

Requisitos de tipo
-
InputIt debe cumplir los requisitos de LegacyInputIterator.

Valor de retorno

acc después de todas las modificaciones.

Posible implementación

accumulate (1)
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
    for (; first != last; ++first)
        init = std::move(init) + *first; // std::move since C++20
    
    return init;
}
accumulate (2)
template<class InputIt, class T, class BinaryOperation>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init, BinaryOperation op)
{
    for (; first != last; ++first)
        init = op(std::move(init), *first); // std::move since C++20
    
    return init;
}

Notas

std::accumulate realiza un fold por la izquierda. Para realizar un fold por la derecha, se debe invertir el orden de los argumentos del operador binario y usar iteradores inversos.

Si se deja a la inferencia de tipos, op opera en valores del mismo tipo que init, lo que puede resultar en una conversión no deseada de los elementos del iterador. Por ejemplo, std::accumulate(v.begin(), v.end(), 0) probablemente no da el resultado que uno desea cuando v es de tipo std::vector<double>.

Ejemplo

#include <functional>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
 
int main()
{
    std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    int sum = std::accumulate(v.begin(), v.end(), 0);
    int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
    
    auto dash_fold = [](std::string a, int b)
    {
        return std::move(a) + '-' + std::to_string(b);
    };
    
    std::string s = std::accumulate(std::next(v.begin()), v.end(),
                                    std::to_string(v[0]), // start with first element
                                    dash_fold);
    
    // Right fold using reverse iterators
    std::string rs = std::accumulate(std::next(v.rbegin()), v.rend(),
                                     std::to_string(v.back()), // start with last element
                                     dash_fold);
    
    std::cout << "sum: " << sum << '\n'
              << "product: " << product << '\n'
              << "dash-separated string: " << s << '\n'
              << "dash-separated string (right-folded): " << rs << '\n';
}

Salida:

sum: 55
product: 3628800
dash-separated string: 1-2-3-4-5-6-7-8-9-10
dash-separated string (right-folded): 10-9-8-7-6-5-4-3-2-1

Informes de defectos

Los siguientes informes de defectos que cambian el comportamiento se aplicaron retroactivamente a los estándares C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 242 C++98 op no podía tener efectos secundarios no puede modificar los rangos involucrados

Véase también

calcula las diferencias entre elementos adyacentes en un rango
(plantilla de función)
calcula el producto interno de dos rangos de elementos
(plantilla de función)
calcula la suma parcial de un rango de elementos
(plantilla de función)
(C++17)
similar a std::accumulate, excepto fuera de orden
(plantilla de función)
pliega por la izquierda un rango de elementos
(objeto de función de algoritmo)