Namespaces
Variants

std::accumulate

De fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur plages (C++20)
Algorithmes contraints, par ex. ranges::copy, ranges::sort, ...
Opérations de séquence non modifiantes    
Opérations par lots
(C++17)
Opérations de recherche
Opérations de séquence modificatrices
Opérations de copie
(C++11)
(C++11)
Opérations d'échange
Opérations de transformation
Opérations de génération
Opérations de suppression
Opérations de changement d'ordre
(jusqu'à C++17)(C++11)
(C++20)(C++20)
Opérations d'échantillonnage
(C++17)

Tri et opérations associées
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur plages partitionnées)
Opérations sur les ensembles (sur plages triées)
Opérations de fusion (sur plages triées)
Opérations de tas
Opérations de minimum/maximum
(C++11)
(C++17)
Opérations de comparaison lexicographique
Opérations de permutation


 
 
Défini dans l'en-tête <numeric>
template< class InputIt, class T >
T accumulate( InputIt first, InputIt last, T init );
(1) (constexpr depuis C++20)
template< class InputIt, class T, class BinaryOp >
T accumulate( InputIt first, InputIt last, T init, BinaryOp op );
(2) (constexpr depuis C++20)

Calcule la somme de la valeur donnée init et des éléments de la plage [firstlast).

1) Initialise l'accumulateur acc (de type T) avec la valeur initiale init puis le modifie avec acc = acc + *i(jusqu'à C++20)acc = std::move(acc) + *i(depuis C++20) pour chaque itérateur i dans la plage [firstlast) dans l'ordre.
2) Initialise l'accumulateur acc (de type T) avec la valeur initiale init puis le modifie avec acc = op(acc, *i)(jusqu'à C++20)acc = op(std::move(acc), *i)(depuis C++20) pour chaque itérateur i dans la plage [firstlast) dans l'ordre.

Si l'une des conditions suivantes est satisfaite, le comportement est indéfini :

  • T n'est pas CopyConstructible.
  • T n'est pas CopyAssignable.
  • op modifie un élément de [firstlast).
  • op invalide un itérateur ou une sous-plage dans [firstlast].

Paramètres

first, last - la paire d'itérateurs définissant la plage d'éléments à accumuler
init - valeur initiale de l'accumulation
op - objet fonction d'opération binaire qui sera appliqué.

La signature de la fonction doit être équivalente à la suivante :

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

La signature n'a pas besoin d'avoir const &.
Le type Type1 doit être tel qu'un objet de type T puisse être implicitement converti en Type1. Le type Type2 doit être tel qu'un objet de type InputIt puisse être déréférencé puis implicitement converti en Type2. Le type Ret doit être tel qu'un objet de type T puisse se voir attribuer une valeur de type Ret. ​

Exigences de type
-
InputIt doit satisfaire les exigences de LegacyInputIterator.

Valeur de retour

acc après toutes les modifications.

Implémentation possible

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;
}

Notes

std::accumulate effectue un pli gauche. Pour effectuer un pli droit, il faut inverser l'ordre des arguments de l'opérateur binaire et utiliser des itérateurs inverses.

Si l'on se fie à l'inférence de type, op opère sur des valeurs du même type que init ce qui peut entraîner un cast indésirable des éléments de l'itérateur. Par exemple, std::accumulate(v.begin(), v.end(), 0) ne donne probablement pas le résultat souhaité lorsque v est de type std::vector<double>.

Exemple

#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';
}

Sortie :

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

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement tel que publié Comportement correct
LWG 242 C++98 op ne pouvait pas avoir d'effets secondaires il ne peut pas modifier les plages impliquées

Voir aussi

calcule les différences entre éléments adjacents dans une plage
(modèle de fonction)
calcule le produit intérieur de deux plages d'éléments
(modèle de fonction)
calcule la somme partielle d'une plage d'éléments
(modèle de fonction)
(C++17)
similaire à std::accumulate, mais hors ordre
(modèle de fonction)
plie à gauche une plage d'éléments
(objet fonction d'algorithme)