std::reduce
| Definiert im Header <numeric>
|
||
template< class InputIt >
typename std::iterator_traits<InputIt>::value_type
reduce( InputIt first, InputIt last );
|
(1) | (seit C++17) (constexpr seit C++20) |
template< class ExecutionPolicy, class ForwardIt >
typename std::iterator_traits<ForwardIt>::value_type
reduce( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last );
|
(2) | (seit C++17) |
template< class InputIt, class T >
T reduce( InputIt first, InputIt last, T init );
|
(3) | (seit C++17) (constexpr seit C++20) |
template< class ExecutionPolicy, class ForwardIt, class T >
T reduce( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, T init );
|
(4) | (seit C++17) |
template< class InputIt, class T, class BinaryOp >
T reduce( InputIt first, InputIt last, T init, BinaryOp op );
|
(5) | (seit C++17) (constexpr seit C++20) |
template< class ExecutionPolicy,
class ForwardIt, class T, class BinaryOp >
T reduce( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt last, T init, BinaryOp op );
|
(6) | (seit C++17) |
reduce(first, last, typename std::iterator_traits<InputIt>::value_type{}).reduce(first, last, init, std::plus<>()).[first, last), möglicherweise in nicht spezifizierter Weise permutiert und aggregiert, zusammen mit dem Anfangswert init über op.policy.true ist:
|
|
(bis C++20) |
|
|
(seit C++20) |
Gegeben binary_op als die tatsächliche binäre Operation:
- Das Ergebnis ist nicht deterministisch, wenn der
binary_opnicht assoziativ oder nicht kommutativ ist (wie z. B. Gleitkommaaddition).
- Wenn einer der folgenden Werte nicht in
Tkonvertierbar ist, ist das Programm fehlerhaft:
binary_op(init, *first)binary_op(*first, init)binary_op(init, init)binary_op(*first, *first)
- Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:
Tist nicht MoveConstructible.binary_opmodifiziert ein Element von[first,last).binary_opmacht einen Iterator oder Teilbereich von[first,last]ungültig.
Parameter
| first, last | - | das Paar von Iteratoren, das den Bereich der Elemente definiert, auf die der Algorithmus angewendet werden soll |
| init | - | der Anfangswert der generalisierten Summe |
| policy | - | die zu verwendende Ausführungsrichtlinie |
| op | - | binäres FunctionObject , das in nicht spezifizierter Reihenfolge auf das Ergebnis der Dereferenzierung der Eingabeiteratoren, die Ergebnisse anderer op und init angewendet wird. |
| Typanforderungen | ||
-
InputIt
muss die Anforderungen von
LegacyInputIterator
erfüllen.
|
||
-
ForwardIt
muss die Anforderungen von
LegacyForwardIterator
erfüllen.
|
||
Rückgabewert
[
first
,
last
)
über
std::
plus
<>
(
)
.
[
first
,
last
)
über
op
.
Die verallgemeinerte Summe einer Gruppe von Elementen über eine binäre Operation binary_op ist wie folgt definiert:
- Wenn die Gruppe nur ein Element hat, ist die Summe der Wert des Elements.
- Andernfalls werden die folgenden Operationen in dieser Reihenfolge ausgeführt:
- Nimmt zwei beliebige Elemente elem1 und elem2 aus der Gruppe.
- Berechnet binary_op ( elem1, elem2 ) und fügt das Ergebnis zurück in die Gruppe ein.
- Wiederholt die Schritte 1 und 2, bis nur noch ein Element in der Gruppe vorhanden ist.
Komplexität
Gegeben N als std:: distance ( first, last ) :
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
ExecutionPolicyeiner der Standard-Policies ist, wird std::terminate aufgerufen. Für jede andereExecutionPolicyist das Verhalten implementierungsdefiniert. - Wenn der Algorithmus keinen Speicher allokieren kann, wird std::bad_alloc geworfen.
Hinweise
std::reduce
verhält sich wie
std::accumulate
, außer dass die Elemente des Bereichs in beliebiger Reihenfolge gruppiert und neu angeordnet werden können.
Beispiel
Gegenüberstellung von
std::reduce
und
std::accumulate
:
#if PARALLEL #include <execution> #define SEQ std::execution::seq, #define PAR std::execution::par, #else #define SEQ #define PAR #endif #include <chrono> #include <iomanip> #include <iostream> #include <locale> #include <numeric> #include <utility> #include <vector> int main() { std::cout.imbue(std::locale("en_US.UTF-8")); std::cout << std::fixed << std::setprecision(1); auto eval = [](auto fun) { const auto t1 = std::chrono::high_resolution_clock::now(); const auto [name, result] = fun(); const auto t2 = std::chrono::high_resolution_clock::now(); const std::chrono::duration<double, std::milli> ms = t2 - t1; std::cout << std::setw(28) << std::left << name << "Summe: " << result << '\t' << "Zeit: " << ms.count() << " ms\n"; }; { const std::vector<double> v(100'000'007, 0.1); eval([&v]{ return std::pair{"std::accumulate (double)", std::accumulate(v.cbegin(), v.cend(), 0.0)}; }); eval([&v]{ return std::pair{"std::reduce (seq, double)", std::reduce(SEQ v.cbegin(), v.cend())}; }); eval([&v]{ return std::pair{"std::reduce (par, double)", std::reduce(PAR v.cbegin(), v.cend())}; }); } { const std::vector<long> v(100'000'007, 1); eval([&v]{ return std::pair{"std::accumulate (long)", std::accumulate(v.cbegin(), v.cend(), 0l)}; }); eval([&v]{ return std::pair{"std::reduce (seq, long)", std::reduce(SEQ v.cbegin(), v.cend())}; }); eval([&v]{ return std::pair{"std::reduce (par, long)", std::reduce(PAR v.cbegin(), v.cend())}; }); } }
Mögliche Ausgabe:
// POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3; ./a.out std::accumulate (double) Summe: 10.000.000,7 Zeit: 356,9 ms std::reduce (seq, double) Summe: 10.000.000,7 Zeit: 140,1 ms std::reduce (par, double) Summe: 10.000.000,7 Zeit: 140,1 ms std::accumulate (long) Summe: 100.000.007 Zeit: 46,0 ms std::reduce (seq, long) Summe: 100.000.007 Zeit: 67,3 ms std::reduce (par, long) Summe: 100.000.007 Zeit: 63,3 ms // POSIX: g++ -std=c++23 ./example.cpp -ltbb -O3 -DPARALLEL; ./a.out std::accumulate (double) Summe: 10.000.000,7 Zeit: 353,4 ms std::reduce (seq, double) Summe: 10.000.000,7 Zeit: 140,7 ms std::reduce (par, double) Summe: 10.000.000,7 Zeit: 24,7 ms std::accumulate (long) Summe: 100.000.007 Zeit: 42,4 ms std::reduce (seq, long) Summe: 100.000.007 Zeit: 52,0 ms std::reduce (par, long) Summe: 100.000.007 Zeit: 23,1 ms
Siehe auch
| summiert oder faltet einen Bereich von Elementen (Funktionsschablone) | |
| wendet eine Funktion auf einen Bereich von Elementen an und speichert die Ergebnisse in einem Zielbereich (Funktionsschablone & Algorithmus-Funktionsobjekt) | |
(C++20) |
|
(C++17) |
wendet ein aufrufbares Objekt an und reduziert dann in beliebiger Reihenfolge (Funktionsschablone) |
(C++23) |
faltet einen Bereich von Elementen von links (Algorithmus-Funktionsobjekt) |