Namespaces
Variants

std::inner_product

Von de.cppreference.net
 
 
Algorithmenbibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z. B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Stapeloperationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Erzeugungsoperationen
Entfernungsoperationen
Reihenfolgeändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
 
Definiert in Header <numeric>
template< class InputIt1, class InputIt2, class T >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init );
(1) (constexpr seit C++20)
template< class InputIt1, class InputIt2, class T,
          class BinaryOp1, class BinaryOp2 >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init,
                 BinaryOp1 op1, BinaryOp2 op2 );
(2) (constexpr seit C++20)

Berechnet das innere Produkt (d. h. Summe der Produkte) oder führt eine geordnete Map/Reduce-Operation auf dem [first1, last1)-Bereich und dem Bereich der std::distance(first1, last1)-Elemente ab first2 durch.

1) Initialisiert den Akkumulator acc (vom Typ T) mit dem Anfangswert init und modifiziert ihn dann mit dem Ausdruck acc = acc + (*i1) * (*i2)(bis C++20)acc = std::move(acc) + (*i1) * (*i2)(seit C++20) für jeden Iterator i1 im Bereich [first1, last1) in der Reihenfolge und seinen zugehörigen Iterator i2 im Bereich ab first2. Bei der eingebauten Bedeutung von + und * berechnet dies das innere Produkt der beiden Bereiche.
2) Initialisiert den Akkumulator acc (vom Typ T) mit dem Anfangswert init und modifiziert ihn dann mit dem Ausdruck acc = op1(acc, op2(*i1, *i2))(bis C++20)acc = op1(std::move(acc), op2(*i1, *i2))(seit C++20) für jeden Iterator i1 im Bereich [first1, last1) in der Reihenfolge und seinen zugehörigen Iterator i2 im Bereich ab first2.

Gegeben last2 als der std::distance(first1, last1)-te nächste Iterator von first2. Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:

  • T ist nicht CopyConstructible.
  • T ist nicht CopyAssignable.
  • op1 oder op2 modifiziert ein Element von [first1, last1) oder [first2, last2).
  • op1 oder op2 macht einen Iterator oder Teilbereich in [first1, last1] oder [first2, last2] ungültig.

Parameter

first1, last1 - das Iteratorpaar, das den Bereich der zu verarbeitenden Elemente definiert
first2 - der Anfang des zweiten Bereichs von Elementen
init - Anfangswert der Summe der Produkte
op1 - binäres Operationsfunktionsobjekt, das angewendet wird. Diese "Summen"-Funktion nimmt einen von op2 zurückgegebenen Wert und den aktuellen Wert des Akkumulators entgegen und erzeugt einen neuen Wert, der im Akkumulator gespeichert wird.

Die Signatur der Funktion sollte der folgenden entsprechen:

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

Die Signatur muss kein const & enthalten.
Die Typen Type1 und Type2 müssen so beschaffen sein, dass Objekte der Typen T bzw. Type3 implizit in Type1 und Type2 konvertiert werden können. Der Typ Ret muss so beschaffen sein, dass einem Objekt des Typs T ein Wert des Typs Ret zugewiesen werden kann. ​

op2 - binäres Operationsfunktionsobjekt, das angewendet wird. Diese "Produkt"-Funktion nimmt einen Wert aus jedem Bereich entgegen und erzeugt einen neuen Wert.

Die Signatur der Funktion sollte der folgenden entsprechen:

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

Die Signatur muss kein const & enthalten.
Die Typen Type1 und Type2 müssen so beschaffen sein, dass Objekte der Typen InputIt1 bzw. InputIt2 dereferenziert und dann implizit in Type1 und Type2 konvertiert werden können. Der Typ Ret muss so beschaffen sein, dass einem Objekt des Typs Type3 ein Wert des Typs Ret zugewiesen werden kann. ​

Typanforderungen
-
InputIt1, InputIt2 muss die Anforderungen von LegacyInputIterator erfüllen.

Rückgabewert

acc nach allen Modifikationen.

Mögliche Implementierung

inner_product (1)
template<class InputIt1, class InputIt2, class T>
constexpr // since C++20
T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init)
{
    while (first1 != last1)
    {
        init = std::move(init) + (*first1) * (*first2); // std::move since C++20
        ++first1;
        ++first2;
    }
    
    return init;
}
inner_product (2)
template<class InputIt1, class InputIt2, class T,
         class BinaryOp1, class BinaryOp2>
constexpr // since C++20
T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init,
                BinaryOp1 op1, BinaryOp2 op2)
{
    while (first1 != last1)
    {
        init = op1(std::move(init), op2(*first1, *first2)); // std::move since C++20
        ++first1;
        ++first2;
    }
    
    return init;
}

Hinweise

Die parallelisierbare Version dieses Algorithmus, std::transform_reduce, erfordert, dass op1 und op2 kommutativ und assoziativ sind, aber std::inner_product stellt keine solche Anforderung und führt die Operationen stets in der angegebenen Reihenfolge aus.

Beispiel

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

int main()
{
    std::vector<int> a{0, 1, 2, 3, 4};
    std::vector<int> b{5, 4, 2, 3, 1};
    
    int r1 = std::inner_product(a.begin(), a.end(), b.begin(), 0);
    std::cout << "Inner product of a and b: " << r1 << '\n';
    
    int r2 = std::inner_product(a.begin(), a.end(), b.begin(), 0,
                                std::plus<>(), std::equal_to<>());
    std::cout << "Number of pairwise matches between a and b: " <<  r2 << '\n';
}

Ausgabe:

Inner product of a and b: 21
Number of pairwise matches between a and b: 2

Fehlerberichte

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

DR Angewendet auf Verhalten wie veröffentlicht Richtiges Verhalten
LWG 242 C++98 op1 und op2 durften keine Nebenwirkungen haben sie dürfen die beteiligten Bereiche nicht modifizieren

Siehe auch

wendet ein aufrufbares Objekt an und reduziert dann in beliebiger Reihenfolge
(Funktionstemplate)
summiert oder faltet einen Bereich von Elementen
(Funktionstemplate)
berechnet die Partialsumme eines Bereichs von Elementen
(Funktionstemplate)