std:: adjacent_difference
|
Défini dans l'en-tête
<numeric>
|
||
|
template
<
class
InputIt,
class
OutputIt
>
OutputIt adjacent_difference
(
InputIt first, InputIt last,
|
(1) | (constexpr depuis C++20) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt1,
class
ForwardIt2
>
|
(2) | (depuis C++17) |
|
template
<
class
InputIt,
class
OutputIt,
class
BinaryOp
>
OutputIt adjacent_difference
(
InputIt first, InputIt last,
|
(3) | (constexpr depuis C++20) |
|
template
<
class
ExecutionPolicy,
class
ForwardIt1,
class
ForwardIt2,
class
BinaryOp
>
|
(4) | (depuis C++17) |
Soit
T
le type de valeur de
decltype
(
first
)
.
[
first
,
last
)
est vide, ne fait rien.
-
Crée un accumulateur
acc
de type
T, et l'initialise avec * first . - Assigne acc à * d_first .
-
Pour chaque itérateur
iter
dans
[++ first,last)dans l'ordre, effectue les opérations suivantes dans l'ordre :
T
, et l'initialise avec
*
iter
.
[
first
,
last
)
est vide, ne fait rien.
- Assigne * first à * d_first .
-
Pour chaque entier
i
dans
[1,std:: distance ( first, last )), effectue les opérations suivantes dans l'ordre :
É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) :
-
-
Tn'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].
-
Pour les surcharges
(2,4)
,
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
&
.
|
| 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 ) :
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
ExecutionPolicyfait partie des politiques standard , std::terminate est appelé. Pour tout autreExecutionPolicy, 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) |