std::for_each
| Definiert in Header <algorithm> |
||
template< class InputIt, class UnaryFunc > UnaryFunc for_each( InputIt first, InputIt last, UnaryFunc f ); |
(1) | (constexpr seit C++20) |
template< class ExecutionPolicy, class ForwardIt, class UnaryFunc > void for_each( ExecutionPolicy&& policy, |
(2) | (seit C++17) |
Wendet das gegebene unäre Funktionsobjekt f auf das Ergebnis der Dereferenzierung jedes Iterators im Bereich [first, last) an. Wenn f ein Ergebnis zurückgibt, wird dieses ignoriert.
|
Wenn |
(seit C++11) |
|
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> ist true. |
(bis C++20) |
|
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> ist true. |
(seit C++20) |
Wenn der Iterator-Typ (InputIt/ForwardIt) veränderbar ist, darf f die Elemente des Bereichs über den dereferenzierten Iterator modifizieren.
Im Gegensatz zu den anderen parallelen Algorithmen darf for_each keine Kopien der Elemente der Sequenz erstellen, auch wenn diese TriviallyCopyable sind.
Inhalt |
[edit] Parameter
| first, last | - | das Paar von Iteratoren, das den Bereich von Elementen definiert, auf die das Funktionsobjekt angewendet wird |
| policy | - | die Ausführungsrichtlinie, die verwendet werden soll |
| f | - | Funktionsobjekt, das auf das Ergebnis der Dereferenzierung jedes Iterators im Bereich [first, last) angewendet wirdDie Signatur der Funktion sollte äquivalent zu folgender sein: void fun(const Type &a); Die Signatur muss nicht const & haben. |
| Typanforderungen | ||
-InputIt muss die Anforderungen von LegacyInputIterator erfüllen. | ||
-ForwardIt muss die Anforderungen von LegacyForwardIterator erfüllen. | ||
[edit] Rückgabewert
[edit] Komplexität
Genau std::distance(first, last) Anwendungen von f.
[edit] Ausnahmen
Die Überladung mit einem Template-Parameter namens ExecutionPolicy meldet Fehler wie folgt
- Wenn die Ausführung einer Funktion, die als Teil des Algorithmus aufgerufen wird, eine Ausnahme auslöst und
ExecutionPolicyeine der Standardrichtlinien ist, wird std::terminate aufgerufen. Für jede andereExecutionPolicyist das Verhalten implementierungsabhängig. - Wenn dem Algorithmus der Speicher zur Neuzuweisung fehlt, wird std::bad_alloc ausgelöst.
[edit] Mögliche Implementierung
Siehe auch die Implementierungen in libstdc++, libc++ und MSVC stdlib.
template<class InputIt, class UnaryFunc> constexpr UnaryFunc for_each(InputIt first, InputIt last, UnaryFunc f) { for (; first != last; ++first) f(*first); return f; // implicit move since C++11 } |
[edit] Anmerkungen
Für Überladung (1) kann f ein zustandsbehaftetes Funktionsobjekt sein. Der Rückgabewert kann als der finale Zustand des Batch-Vorgangs betrachtet werden.
Für Überladung (2) können mehrere Kopien von f erstellt werden, um parallele Aufrufe durchzuführen. Es wird kein Wert zurückgegeben, da die Parallelisierung oft keine effiziente Zustandsakkumulation erlaubt.
[edit] Beispiel
Das folgende Beispiel verwendet einen Lambda-Ausdruck, um alle Elemente eines Vektors zu inkrementieren, und dann eine überladene operator() in einem Funktionsobjekt (auch "Funktor" genannt), um ihre Summe zu berechnen. Beachten Sie, dass zum Berechnen der Summe die Verwendung des dedizierten Algorithmus std::accumulate empfohlen wird.
#include <algorithm> #include <iostream> #include <vector> int main() { std::vector<int> v{3, -4, 2, -8, 15, 267}; auto print = [](const int& n) { std::cout << n << ' '; }; std::cout << "before:\t"; std::for_each(v.cbegin(), v.cend(), print); std::cout << '\n'; // increment elements in-place std::for_each(v.begin(), v.end(), [](int &n) { n++; }); std::cout << "after:\t"; std::for_each(v.cbegin(), v.cend(), print); std::cout << '\n'; struct Sum { void operator()(int n) { sum += n; } int sum {0}; }; // invoke Sum::operator() for each element Sum s = std::for_each(v.cbegin(), v.cend(), Sum()); std::cout << "sum:\t" << s.sum << '\n'; }
Ausgabe
before: 3 -4 2 -8 15 267 after: 4 -3 3 -7 16 268 sum: 281
[edit] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 475 | C++98 | war unklar, ob f die Elemente der durchlaufenen Sequenz ändern kann ( for_each ist als "nicht-modifizierende Sequenzoperationen" klassifiziert) |
wurde klargestellt (erlaubt, wenn der Iterator-Typ veränderbar ist) |
| LWG 2747 | C++11 | Überladung (1) gab std::move(f) zurück | gibt f zurück (was implizit verschiebt) |
[edit] Siehe auch
| Wendet eine Funktion auf einen Elementbereich an und speichert die Ergebnisse in einem Zielbereich (Funktionstempelat) | |
| (C++17) |
Wendet ein Funktionsobjekt auf die ersten N Elemente einer Sequenz an (Funktionstempelat) |
| (C++20) |
wendet ein unäres Funktionsobjekt auf Elemente aus einem Bereich an (Algorithmus-Funktionsobjekt) |
| (C++20) |
Wendet ein Funktionsobjekt auf die ersten N Elemente einer Sequenz an (Algorithmus-Funktionsobjekt) |
Bereichs-for-Schleife(C++11) |
führt Schleife über einen Bereich aus |