Namespaces
Variants

std::partial_sum

Depuis fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur plages (C++20)
Algorithmes contraints, p. ex. ranges::copy, ranges::sort, ...
Opérations de séquence non modificatrices    
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 connexes
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur plages partitionnées)
Opérations d'ensemble (sur plages triées)
Opérations de fusion (sur plages triées)
Opérations de tas
Opérations 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 OutputIt >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first );
(1) (constexpr depuis C++20)
template< class InputIt, class OutputIt, class BinaryOp >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first, BinaryOp op );
(2) (constexpr depuis C++20)
1) Si [firstlast) est vide, ne fait rien.
Sinon, effectue les opérations suivantes dans l'ordre :
  1. Crée un accumulateur acc, dont le type est le type valeur de InputIt, et l'initialise avec *first.
  2. Affecte acc à *d_first.
  3. Pour chaque entier i dans [1std::distance(first, last)), effectue les opérations suivantes dans l'ordre :
a) Calcule acc + *iter(jusqu'à C++20)std::move(acc) + *iter(depuis C++20), où iter est l'itérateur suivant le i-ième de first.
b) Affecte le résultat à acc.
c) Affecte acc[1] à *dest, où dest est l'itérateur suivant le i-ième de d_first.
2) Identique à (1), mais calcule op(acc, *iter)(jusqu'à C++20)op(std::move(acc), *iter)(depuis C++20) à la place.

Étant donné binary_op comme opération binaire réelle :

  • Si l'une des conditions suivantes est satisfaite, le programme est mal formé :
  • Le type valeur de InputIt n'est pas constructible à partir de *first.
  • acc n'est pas inscriptible dans d_first.
  • Le résultat de binary_op(acc, *iter)(jusqu'à C++20)binary_op(std::move(acc), *iter)(depuis C++20) n'est pas implicitement convertible au type valeur de InputIt.
  • Étant donné d_last comme l'itérateur à retourner, si l'une des conditions suivantes est satisfaite, le comportement est indéfini :
  • binary_op modifie tout élément de [firstlast) ou [d_firstd_last).
  • binary_op invalide un itérateur ou une sous-plage dans [firstlast] ou [d_firstd_last].


  1. La valeur réelle à affecter est le résultat de l'affectation à l'étape précédente. Nous supposons que le résultat de l'affectation est acc ici.

Paramètres

first, last - la paire d'itérateurs définissant la plage d'éléments à sommer
d_first - le début de la plage de destination ; peut être égal à first
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 std::iterator_traits<InputIt>::value_type 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 InputIt puisse être déréférencé et qu'une valeur de type Ret puisse lui être affectée. ​

Exigences de type
-
InputIt doit satisfaire aux exigences de LegacyInputIterator.
-
OutputIt doit satisfaire aux exigences de LegacyOutputIterator.

Valeur de retour

Itérateur vers l'élément après le dernier élément écrit, ou d_first si [firstlast) est vide.

Complexité

Étant donné N comme std::distance(first, last) :

1) Exactement N-1 applications de operator+.
2) Exactement N-1 applications de la fonction binaire op.

Implémentation possible

partial_sum (1)
template<class InputIt, class OutputIt>
constexpr // since C++20
OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first)
{
    if (first == last)
        return d_first;
    
    typename std::iterator_traits<InputIt>::value_type sum = *first;
    *d_first = sum;
    
    while (++first != last)
    {
        sum = std::move(sum) + *first; // std::move since C++20
        *++d_first = sum;
    }
    
    return ++d_first;
    
    // or, since C++14:
    // return std::partial_sum(first, last, d_first, std::plus<>());
}
partial_sum (2)
template<class InputIt, class OutputIt, class BinaryOp>
constexpr // since C++20
OutputIt partial_sum(InputIt first, InputIt last, 
                     OutputIt d_first, BinaryOp op)
{
    if (first == last)
        return d_first;
    
    typename std::iterator_traits<InputIt>::value_type acc = *first;
    *d_first = acc;
    
    while (++first != last)
    {
        acc = op(std::move(acc), *first); // std::move since C++20
        *++d_first = acc;
    }
    
    return ++d_first;
}

Notes

acc a été introduit à cause de la résolution de LWG issue 539. La raison d'utiliser acc plutôt que de sommer directement les résultats (c'est-à-dire *(d_first + 2) = (*first + *(first + 1)) + *(first + 2);) est que la sémantique de ce dernier est déroutante si les types suivants ne correspondent pas :

  • le type valeur de InputIt
  • les types inscriptibles de OutputIt
  • les types des paramètres de operator+ ou op
  • le type de retour de operator+ ou op

acc sert d'objet intermédiaire pour stocker et fournir les valeurs à chaque étape du calcul :

  • son type est le type valeur de InputIt
  • il est écrit dans d_first
  • sa valeur est passée à operator+ ou op
  • il stocke la valeur de retour de operator+ ou op
enum not_int { x = 1, y = 2 };

char i_array[4] = {100, 100, 100, 100};
not_int e_array[4] = {x, x, y, y};
int  o_array[4];

// OK: uses operator+(char, char) and assigns char values to int array
std::partial_sum(i_array, i_array + 4, o_array);

// Error: cannot assign not_int values to int array
std::partial_sum(e_array, e_array + 4, o_array);

// OK: performs conversions when needed
// 1. creates “acc” of type char (the value type)
// 2. the char arguments are used for long multiplication (char -> long)
// 3. the long product is assigned to “acc” (long -> char)
// 4. “acc” is assigned to an element of “o_array” (char -> int)
// 5. go back to step 2 to process the remaining elements in the input range
std::partial_sum(i_array, i_array + 4, o_array, std::multiplies<long>{});

Exemple

#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

int main()
{
    std::vector<int> v(10, 2); // v = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
    
    std::cout << "The first " << v.size() << " even numbers are: ";
    // write the result to the cout stream
    std::partial_sum(v.cbegin(), v.cend(), 
                     std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
    
    // write the result back to the vector v
    std::partial_sum(v.cbegin(), v.cend(),
                     v.begin(), std::multiplies<int>());
    
    std::cout << "The first " << v.size() << " powers of 2 are: ";
    for (int n : v)
        std::cout << n << ' ';
    std::cout << '\n';
}

Sortie :

The first 10 even numbers are: 2 4 6 8 10 12 14 16 18 20 
The first 10 powers of 2 are: 2 4 8 16 32 64 128 256 512 1024

Rapports de bogues

Les rapports de bogues suivants modifiant le comportement 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 de bord il ne peut pas modifier les plages concernées
LWG 539 C++98 les exigences de type nécessaires pour que les résultats
évaluations et affectations soient valides étaient manquantes
ajoutées

Voir aussi

calcule les différences entre éléments adjacents dans une plage
(patron de fonction)
additionne ou plie une plage d'éléments
(patron de fonction)
similaire à std::partial_sum, inclut le i-ième élément d'entrée dans la i-ième somme
(patron de fonction)
similaire à std::partial_sum, exclut le i-ième élément d'entrée de la i-ième somme
(patron de fonction)