Namespaces
Variants

std:: accumulate

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
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 se satisface cualquiera de las siguientes condiciones, el comportamiento es indefinido:

Contenidos

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 será aplicado.

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 convertido 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 con los requisitos de LegacyInputIterator .

Valor de retorno

acc después de todas las modificaciones.

Implementación posible

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 plegado hacia la izquierda. Para realizar un plegado hacia la derecha, se debe invertir el orden de los argumentos al operador binario y utilizar iteradores inversos.

Si se deja a la inferencia de tipos, op opera sobre valores del mismo tipo que init lo cual puede resultar en conversiones no deseadas de los elementos del iterador. Por ejemplo, std :: accumulate ( v. begin ( ) , v. end ( ) , 0 ) probablemente no da el resultado que se 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]), // comenzar con el primer elemento
                                    dash_fold);
    // Plegado hacia la derecha usando iteradores inversos
    std::string rs = std::accumulate(std::next(v.rbegin()), v.rend(),
                                     std::to_string(v.back()), // comenzar con el último elemento
                                     dash_fold);
    std::cout << "suma: " << sum << '\n'
              << "producto: " << product << '\n'
              << "cadena separada por guiones: " << s << '\n'
              << "cadena separada por guiones (plegado derecho): " << rs << '\n';
}

Salida:

suma: 55
producto: 3628800
cadena separada por guiones: 1-2-3-4-5-6-7-8-9-10
cadena separada por guiones (plegado derecho): 10-9-8-7-6-5-4-3-2-1

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de 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 hacia la izquierda un rango de elementos
(objeto función de algoritmo)