Namespaces
Variants

std:: adjacent_difference

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
(C++11)
adjacent_difference
Operations on uninitialized memory
Défini dans l'en-tête <numeric>
template < class InputIt, class OutputIt >

OutputIt adjacent_difference ( InputIt first, InputIt last,

OutputIt d_first ) ;
(1) (constexpr depuis C++20)
template < class ExecutionPolicy,

class ForwardIt1, class ForwardIt2 >
ForwardIt2 adjacent_difference ( ExecutionPolicy && policy,
ForwardIt1 first, ForwardIt1 last,

ForwardIt2 d_first ) ;
(2) (depuis C++17)
template < class InputIt, class OutputIt, class BinaryOp >

OutputIt adjacent_difference ( InputIt first, InputIt last,

OutputIt d_first, BinaryOp op ) ;
(3) (constexpr depuis C++20)
template < class ExecutionPolicy,

class ForwardIt1, class ForwardIt2, class BinaryOp >
ForwardIt2 adjacent_difference ( ExecutionPolicy && policy,
ForwardIt1 first, ForwardIt1 last,

ForwardIt2 d_first, BinaryOp op ) ;
(4) (depuis C++17)

Soit T le type de valeur de decltype ( first ) .

1) Si [ first , last ) est vide, ne fait rien.
Sinon, effectue les opérations suivantes dans l'ordre :
  1. Crée un accumulateur acc de type T , et l'initialise avec * first .
  2. Assigne acc à * d_first .
  3. Pour chaque itérateur iter dans [ ++ first , last ) dans l'ordre, effectue les opérations suivantes dans l'ordre :
a) Crée un objet val de type T , et l'initialise avec * iter .
b) Calcule val - acc (jusqu'en C++20) val - std :: move ( acc ) (depuis C++20) .
c) Affecte le résultat à *++ d_first .
d) Copie (jusqu'en C++20) Déplacement (depuis C++20) assigne depuis val vers acc .
2) Si [ first , last ) est vide, ne fait rien.
Sinon, effectue les opérations suivantes dans l'ordre :
  1. Assigne * first à * d_first .
  2. Pour chaque entier i dans [ 1 , std:: distance ( first, last ) ) , effectue les opérations suivantes dans l'ordre :
a) Calcule curr - prev , où curr est le prochain i ème itérateur de first , et prev est le prochain i - 1 ème itérateur de first .
b) Affecte le résultat à * dest , où dest est le i ième itérateur suivant de d_first .
3) Identique à (1) , mais calcule op ( val, acc ) (jusqu'à C++20) op ( val, std :: move ( acc ) ) (depuis C++20) à la place.
4) Identique à (2) , mais calcule op ( curr, prev ) à la place.

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

  • Si l'une des conditions suivantes est satisfaite, le programme est mal formé :
  • Pour les surcharges (1,3) :
  • T n'est pas constructible à partir de * first .
  • acc n'est pas accessible en écriture vers d_first .
  • Le résultat de binary_op ( val, acc ) (jusqu'à C++20) binary_op ( val, std :: move ( acc ) ) (depuis C++20) n'est pas accessible en écriture vers d_first .
  • Pour les surcharges (2,4) :
  • * first n'est pas accessible en écriture vers d_first .
  • Le résultat de binary_op ( * first, * first ) n'est pas accessible en écriture vers d_first .
  • Étant donné d_last comme l'itérateur à être retourné , si l'une des conditions suivantes est satisfaite, le comportement est indéfini :
(depuis C++20)
  • Pour les surcharges (2,4) , [ first , last ) et [ d_first , d_last ) se chevauchent.
  • binary_op modifie tout élément de [ first , last ) ou [ d_first , d_last ) .
  • binary_op invalide tout itérateur ou sous-intervalle dans [ first , last ] ou [ d_first , d_last ] .

Table des matières

Paramètres

first, last - la paire d'itérateurs définissant l'intervalle des éléments à
d_first - le début de l'intervalle de destination
policy - la politique d'exécution à utiliser
op - objet fonction d'opération binaire qui sera appliqué.

La signature de la fonction doit être équivalente à ce qui suit :

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

La signature n'a pas besoin d'avoir const & .
Les types Type1 et Type2 doivent être tels qu'un objet de type iterator_traits < InputIt > :: value_type puisse être implicitement converti vers les deux. Le type Ret doit être tel qu'un objet de type OutputIt puisse être déréférencé et assigné d'une valeur de type Ret . ​

Exigences de type
-
InputIt doit satisfaire aux exigences de LegacyInputIterator .
-
OutputIt doit satisfaire aux exigences de LegacyOutputIterator .
-
ForwardIt1, ForwardIt2 doit satisfaire aux exigences de LegacyForwardIterator .

Valeur de retour

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

Complexité

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

1,2) Exactement N-1 applications de operator - .
3,4) Exactement N-1 applications de la fonction binaire op .

Exceptions

Les surcharges avec un paramètre de modèle nommé ExecutionPolicy signalent les erreurs comme suit :

  • Si l'exécution d'une fonction invoquée dans le cadre de l'algorithme lève une exception et que ExecutionPolicy fait partie des politiques standard , std::terminate est appelé. Pour tout autre ExecutionPolicy , le comportement est défini par l'implémentation.
  • Si l'algorithme ne parvient pas à allouer de la mémoire, std::bad_alloc est levé.

Implémentation possible

adjacent_difference (1)
template<class InputIt, class OutputIt>
constexpr // depuis C++20
OutputIt adjacent_difference(InputIt first, InputIt last, OutputIt d_first)
{
    if (first == last)
        return d_first;
    typedef typename std::iterator_traits<InputIt>::value_type value_t;
    value_t acc = *first;
    *d_first = acc;
    while (++first != last)
    {
        value_t val = *first;
        *++d_first = val - std::move(acc); // std::move depuis C++20
        acc = std::move(val);
    }
    return ++d_first;
}
adjacent_difference (3)
template<class InputIt, class OutputIt, class BinaryOp>
constexpr // depuis C++20
OutputIt adjacent_difference(InputIt first, InputIt last, 
                             OutputIt d_first, BinaryOp op)
{
    if (first == last)
        return d_first;
    typedef typename std::iterator_traits<InputIt>::value_type value_t;
    value_t acc = *first;
    *d_first = acc;
    while (++first != last)
    {
        value_t val = *first;
        *++d_first = op(val, std::move(acc)); // std::move depuis C++20
        acc = std::move(val);
    }
    return ++d_first;
}

Notes

acc a été introduit en raison de la résolution de LWG issue 539 . La raison d'utiliser acc plutôt que de calculer directement les différences est que la sémantique de cette dernière approche est confuse si les types suivants ne correspondent pas :

  • le type de valeur de InputIt
  • le(s) type(s) accessible en écriture 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 mettre en cache les valeurs des éléments itérés :

  • son type est le type de valeur de InputIt
  • la valeur écrite dans d_first (qui est la valeur de retour de operator - ou op ) lui est assignée
  • sa valeur est passée à operator - ou op
char i_array[4] = {100, 100, 100, 100};
int  o_array[4];
// OK : effectue les conversions lorsque nécessaire
// 1. crée "acc" de type char (le type de valeur)
// 2. "acc" est assigné au premier élément de "o_array"
// 3. les arguments char sont utilisés pour la multiplication longue (char -> long)
// 4. le produit long est assigné à la plage de sortie (long -> int)
// 5. la valeur suivante de "i_array" est assignée à "acc"
// 6. retour à l'étape 3 pour traiter les éléments restants dans la plage d'entrée
std::adjacent_difference(i_array, i_array + 4, o_array, std::multiplies<long>{});

Exemple

#include <array>
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
void println(auto comment, const auto& sequence)
{
    std::cout << comment;
    for (const auto& n : sequence)
        std::cout << n << ' ';
    std::cout << '\n';
};
int main()
{
    // Implémentation par défaut - la différence entre deux éléments adjacents
    std::vector v{4, 6, 9, 13, 18, 19, 19, 15, 10};
    println("Initialement, v = ", v);
    std::adjacent_difference(v.begin(), v.end(), v.begin());
    println("v modifié = ", v);
    // Fibonacci
    std::array<int, 10> a {1};
    std::adjacent_difference(std::begin(a), std::prev(std::end(a)),
                             std::next(std::begin(a)), std::plus<>{});
    println("Fibonacci, a = ", a);
}

Sortie :

Initialement, v = 4 6 9 13 18 19 19 15 10 
v modifié = 4 2 3 4 5 1 0 -4 -5 
Fibonacci, a = 1 1 2 3 5 8 13 21 34 55

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 Applicable à Comportement publié Comportement corrigé
LWG 242 C++98 op ne pouvait pas avoir d'effets secondaires il ne peut pas modifier
les plages concernées
LWG 539 C++98 les exigences de type nécessaires pour la validité
des évaluations de résultat et des assignations manquaient
ajoutées
LWG 3058 C++17 pour les surcharges (2,4) , le résultat de chaque invocation
de operator - ou op était assigné à un objet temporaire,
et cet objet est assigné à la plage de sortie
assigner directement les résultats
à la plage
de sortie

Voir aussi

calcule la somme partielle d'une plage d'éléments
(modèle de fonction)
additionne ou replie une plage d'éléments
(modèle de fonction)