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
Definiert im Header <numeric>
template < class InputIt, class OutputIt >

OutputIt adjacent_difference ( InputIt first, InputIt last,

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

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

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

OutputIt adjacent_difference ( InputIt first, InputIt last,

OutputIt d_first, BinaryOp op ) ;
(3) (constexpr seit 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) (seit C++17)

Sei T der Werttyp von decltype ( first ) .

1) Wenn [ first , last ) leer ist, tut nichts.
Andernfalls werden die folgenden Operationen in der Reihenfolge ausgeführt:
  1. Erstellt einen Akkumulator acc vom Typ T und initialisiert ihn mit * first .
  2. Weist acc an * d_first zu.
  3. Für jeden Iterator iter in [ ++ first , last ) in der Reihenfolge werden die folgenden Operationen ausgeführt:
a) Erzeugt ein Objekt val vom Typ T und initialisiert es mit * iter .
b) Berechnet val - acc (bis C++20) val - std :: move ( acc ) (seit C++20) .
c) Weist das Ergebnis *++ d_first zu.
d) Copy (until C++20) Move (since C++20) weist von val zu acc .
2) Wenn [ first , last ) leer ist, tut nichts.
Andernfalls werden die folgenden Operationen in der Reihenfolge ausgeführt:
  1. Weist * first an * d_first zu.
  2. Für jede ganze Zahl i in [ 1 , std:: distance ( first, last ) ) , werden die folgenden Operationen in der Reihenfolge ausgeführt:
a) Berechnet curr - prev , wobei curr der nächste i te Iterator von first ist und prev der nächste i - 1 te Iterator von first ist.
b) Weist das Ergebnis * dest zu, wobei dest der nächste i te Iterator von d_first ist.
3) Gleich wie (1) , berechnet jedoch op ( val, acc ) (bis C++20) op ( val, std :: move ( acc ) ) (seit C++20) stattdessen.
4) Gleich wie (2) , berechnet jedoch op ( curr, prev ) stattdessen.

Gegeben binary_op als die tatsächliche binäre Operation:

  • Wenn eine der folgenden Bedingungen erfüllt ist, ist das Programm fehlerhaft:
  • Für Überladungen (1,3) :
  • T ist nicht konstruierbar aus * first .
  • acc ist nicht schreibbar nach d_first .
  • Das Ergebnis von binary_op ( val, acc ) (bis C++20) binary_op ( val, std :: move ( acc ) ) (seit C++20) ist nicht schreibbar nach d_first .
  • Für Überladungen (2,4) :
  • * first ist nicht schreibbar nach d_first .
  • Das Ergebnis von binary_op ( * first, * first ) ist nicht schreibbar nach d_first .
  • Gegeben sei d_last als der zurückzugebende Iterator, falls eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:
(seit C++20)
  • Für Überladungen (2,4) überlappen sich [ first , last ) und [ d_first , d_last ) .
  • binary_op modifiziert irgendein Element von [ first , last ) oder [ d_first , d_last ) .
  • binary_op macht irgendeinen Iterator oder Teilbereich in [ first , last ] oder [ d_first , d_last ] ungültig.

Inhaltsverzeichnis

Parameter

first, last - das Paar von Iteratoren, das den Bereich der Elemente definiert, die
d_first - der Anfang des Zielbereichs
policy - die zu verwendende Ausführungsrichtlinie
op - binäres Funktionsobjekt, das angewendet wird.

Die Signatur der Funktion sollte äquivalent zu Folgendem sein:

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

Die Signatur muss nicht const & haben.
Die Typen Type1 und Type2 müssen so beschaffen sein, dass ein Objekt vom Typ iterator_traits < InputIt > :: value_type implizit in beide konvertiert werden kann. Der Typ Ret muss so beschaffen sein, dass ein Objekt vom Typ OutputIt dereferenziert und ein Wert vom Typ Ret zugewiesen werden kann. ​

Typanforderungen
-
InputIt muss die Anforderungen von LegacyInputIterator erfüllen.
-
OutputIt muss die Anforderungen von LegacyOutputIterator erfüllen.
-
ForwardIt1, ForwardIt2 muss die Anforderungen von LegacyForwardIterator erfüllen.

Rückgabewert

Iterator auf das Element nach dem letzten geschriebenen Element, oder d_first falls [ first , last ) leer ist.

Komplexität

Gegeben N als std:: distance ( first, last ) :

1,2) Genau N-1 Anwendungen des operator - .
3,4) Genau N-1 Anwendungen der binären Funktion op .

Ausnahmen

Die Überladungen mit einem Template-Parameter namens ExecutionPolicy melden Fehler wie folgt:

  • Wenn die Ausführung einer als Teil des Algorithmus aufgerufenen Funktion eine Exception wirft und ExecutionPolicy einer der Standard-Policies ist, wird std::terminate aufgerufen. Für jede andere ExecutionPolicy ist das Verhalten implementierungsdefiniert.
  • Wenn der Algorithmus keinen Speicher allokieren kann, wird std::bad_alloc geworfen.

Mögliche Implementierung

adjacent_difference (1)
template<class InputIt, class OutputIt>
constexpr // since 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 since C++20
        acc = std::move(val);
    }
    return ++d_first;
}
adjacent_difference (3)
template<class InputIt, class OutputIt, class BinaryOp>
constexpr // since 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 since C++20
        acc = std::move(val);
    }
    return ++d_first;
}

Hinweise

acc wurde aufgrund der Lösung von LWG Issue 539 eingeführt. Der Grund für die Verwendung von acc anstelle der direkten Berechnung der Differenzen liegt darin, dass die Semantik letzterer verwirrend ist, wenn die folgenden Typen nicht übereinstimmen:

  • der Werttyp von InputIt
  • der schreibbare Typ (oder die schreibbaren Typen) von OutputIt
  • die Typen der Parameter von operator - oder op
  • der Rückgabetyp von operator - oder op

acc dient als Zwischenobjekt zum Zwischenspeichern von Werten der iterierten Elemente:

  • sein Typ ist der Werttyp von InputIt
  • der an d_first geschriebene Wert (welcher der Rückgabewert von operator - oder op ist) wird ihm zugewiesen
  • sein Wert wird an operator - oder op übergeben
char i_array[4] = {100, 100, 100, 100};
int  o_array[4];
// OK: führt Konvertierungen bei Bedarf durch
// 1. erstellt "acc" vom Typ char (der Werttyp)
// 2. "acc" wird dem ersten Element von "o_array" zugewiesen
// 3. die char-Argumente werden für die long-Multiplikation verwendet (char -> long)
// 4. das long-Produkt wird dem Ausgabebereich zugewiesen (long -> int)
// 5. der nächste Wert von "i_array" wird "acc" zugewiesen
// 6. zurück zu Schritt 3, um die verbleibenden Elemente im Eingabebereich zu verarbeiten
std::adjacent_difference(i_array, i_array + 4, o_array, std::multiplies<long>{});

Beispiel

#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()
{
    // Standardimplementierung - die Differenz zwischen zwei benachbarten Elementen
    std::vector v{4, 6, 9, 13, 18, 19, 19, 15, 10};
    println("Anfänglich, v = ", v);
    std::adjacent_difference(v.begin(), v.end(), v.begin());
    println("Modifiziertes v = ", 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);
}

Ausgabe:

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

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
LWG 242 C++98 op durfte keine Nebeneffekte haben es kann die beteiligten
Bereiche nicht modifizieren
LWG 539 C++98 die Typanforderungen für gültige Ergebnisauswertungen
und Zuweisungen fehlten
hinzugefügt
LWG 3058 C++17 für Überladungen (2,4) wurde das Ergebnis jedes Aufrufs
von operator - oder op einem temporären Objekt zugewiesen,
und dieses Objekt wird dem Ausgabebereich zugewiesen
weise die Ergebnisse
direkt dem Ausgabe-
bereich zu

Siehe auch

berechnet die Teilsumme einer Reihe von Elementen
(Funktions-Template)
summiert oder faltet eine Reihe von Elementen
(Funktions-Template)