Namespaces
Variants

std::ranges::for_each, std::ranges::for_each_result

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
Generierungsoperationen
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


 
Eingeschränkte Algorithmen
Alle Namen in diesem Menü gehören zum Namensraum std::ranges
Nicht modifizierende Sequenzoperationen
Modifizierende Sequenzoperationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen (auf sortierten Bereichen)
       
       
Mengenoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
       
       
Permutationsoperationen
Faltungsoperationen
Numerische Operationen
(C++23)            
Operationen auf nicht initialisiertem Speicher
Rückgabetypen
 
Definiert im Header <algorithm>
Aufrufsignatur
template< std::input_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          std::indirectly_unary_invocable<std::projected<I, Proj>> Fun >
constexpr for_each_result<I, Fun>
    for_each( I first, S last, Fun f, Proj proj = {} );
(1) (seit C++20)
template< ranges::input_range R, class Proj = std::identity,
          std::indirectly_unary_invocable
              <std::projected<ranges::iterator_t<R>, Proj>> Fun >
constexpr for_each_result<ranges::borrowed_iterator_t<R>, Fun>
    for_each( R&& r, Fun f, Proj proj = {} );
(2) (seit C++20)
template< /*execution-policy*/ Ep, std::random_access_iterator I,
          std::sized_sentinel_for<I> S, class Proj = std::identity,
          std::indirectly_unary_invocable<std::projected<I, Proj>> Fun >
I for_each( Ep&& policy, I first, S last, Fun f, Proj proj = {} );
(3) (seit C++26)
template< /*execution-policy*/ Ep,
          /*sized-random-access-range*/ R, class Proj = std::identity,
          std::indirectly_unary_invocable
              <std::projected<ranges::iterator_t<R>, Proj>> Fun >
ranges::borrowed_iterator_t<R>
    for_each( Ep&& policy, R&& r, Fun f, Proj proj = {} );
(4) (seit C++26)
Hilfstypen
template< class I, class F >
using for_each_result = ranges::in_fun_result<I, F>;
(5) (seit C++20)

Für die Definition von /*execution-policy*/ siehe diese Seite; für die Definition von /*sized-random-access-range*/ siehe diese Seite.

Wendet das gegebene aufrufbare Objekt f auf jedes Element (projiziert durch proj) im Zielbereich [first, last) oder r an. Wenn f ein Ergebnis zurückgibt, wird das Ergebnis ignoriert.

1,2) f wird der Reihe nach vom Anfang des Zielbereichs angewendet.
3,4) f wird möglicherweise nicht der Reihe nach angewendet. Der Algorithmus wird gemäß policy ausgeführt.
Im Gegensatz zu anderen parallelen Algorithmen ist es for_each nicht erlaubt, beliebige Kopien von Elementen aus dem Zielbereich zu erstellen.

Die funktionsartigen Entitäten, die auf dieser Seite beschrieben werden, sind Algorithmus-Funktionsobjekte (informell als Niebloids bekannt), das heißt:

Parameter

first, last - das Paar von Iteratoren, das den Ziel-bereich
definiert - der Zielbereich
f - das aufrufbare Objekt, das auf die (projizierten) Elemente angewendet werden soll
proj - die Projektion, die auf die Elemente angewendet werden soll
policy - die zu verwendende Ausführungsrichtlinie

Rückgabewert

1) {last, std::move(f)}
2) {ranges::next(ranges::begin(r), ranges::end(r)), std::move(f)} wenn R das Konzept forward_range modelliert, andernfalls (seit C++26){ranges::end(r), std::move(f)}
3) last
4) ranges::next(ranges::begin(r), ranges::end(r)) wenn R das Konzept forward_range modelliert, andernfalls (seit C++26)ranges::end(r)

Komplexität

1,3) Genau ranges::distance(first, last) Anwendungen von f und proj.
2,4) Genau ranges::distance(r) Anwendungen von f und proj.

Ausnahmen

3,4) Während des Ausführungsprozesses:
  • Wenn die für die Parallelisierung erforderlichen temporären Speicherressourcen nicht verfügbar sind, wird std::bad_alloc ausgelöst.
  • Wenn während des Zugriffs auf Objekte über ein Algorithmusargument eine nicht abgefangene Ausnahme ausgelöst wird, wird das Verhalten durch die Ausführungsrichtlinie bestimmt (für Standardrichtlinien wird std::terminate aufgerufen).

Hinweise

Wenn die Projektion eine veränderliche Referenz zurückgibt, kann f die Elemente im Zielbereich verändern.

Für die Überladungen (1,2) kann f ein zustandsbehaftetes aufrufbares Objekt sein. Das aufrufbare Objekt im Rückgabewert kann als Endzustand der Stapeloperation betrachtet werden.

Für die Überladungen (3,4) können mehrere Kopien von f erstellt werden, um parallele Aufrufe durchzuführen. Der Rückgabewert enthält kein aufrufbares Objekt, da Parallelisierung oft keine effiziente Zustandsakkumulation erlaubt.

Mögliche Implementierung

struct for_each_fn
{
    template<std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirectly_unary_invocable<std::projected<I, Proj>> Fun>
    constexpr ranges::for_each_result<I, Fun>
        operator()(I first, S last, Fun f, Proj proj = {}) const
    {
        for (; first != last; ++first)
            std::invoke(f, std::invoke(proj, *first));
        return {std::move(first), std::move(f)};
    }
    
    template<ranges::input_range R, class Proj = std::identity,
             std::indirectly_unary_invocable
                 <std::projected<ranges::iterator_t<R>, Proj>> Fun>
    constexpr ranges::for_each_result<ranges::borrowed_iterator_t<R>, Fun>
        operator()(R&& r, Fun f, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj));
    }
    
    template<ranges::forward_range R, class Proj = std::identity,
             std::indirectly_unary_invocable
                 <std::projected<ranges::iterator_t<R>, Proj>> Fun>
    constexpr ranges::for_each_result<ranges::borrowed_iterator_t<R>, Fun>
        operator()(R&& r, Fun f, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r),
                       ranges::next(ranges::begin(r), ranges::end(r)),
                       std::move(f), std::ref(proj));
    }
};

inline constexpr for_each_fn for_each;

Beispiel

Das folgende Beispiel verwendet einen Lambda-Ausdruck, um alle Elemente eines Vektors zu inkrementieren, und dann eine überladene operator() in einem aufrufbaren Objekt, um deren Summe zu berechnen. Beachten Sie, dass zur Berechnung der Summe der dedizierte Algorithmus std::accumulate empfohlen wird.

#include <algorithm>
#include <cassert>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

struct Sum
{
    void operator()(int n) { sum += n; }
    int sum {0};
};

int main()
{
    namespace ranges = std::ranges;
    
    std::vector<int> nums {3, 4, 2, 8, 15, 267};
    
    auto print = [](const auto& n) { std::cout << ' ' << n; };
    
    std::cout << "before:";
    ranges::for_each(std::as_const(nums), print);
    print('\n');
    
    ranges::for_each(nums, [](int& n) { ++n; });
    
    // calls Sum::operator() for each number
    auto [i, s] = ranges::for_each(nums.begin(), nums.end(), Sum());
    assert(i == nums.end());
    
    std::cout << "after: ";
    ranges::for_each(nums.cbegin(), nums.cend(), print);
    
    std::cout << "\n" "sum: " << s.sum << '\n';
    
    using pair = std::pair<int, std::string>; 
    std::vector<pair> pairs {{1,"one"}, {2,"two"}, {3,"tree"}};
    
    std::cout << "project the pair::first: ";
    ranges::for_each(pairs, print, [](const pair& p) { return p.first; });
    
    std::cout << "\n" "project the pair::second:";
    ranges::for_each(pairs, print, &pair::second);
    print('\n');
}

Ausgabe:

before: 3 4 2 8 15 267 
after:  4 5 3 9 16 268
sum: 305
project the pair::first:  1 2 3
project the pair::second: one two tree

Siehe auch

wendet ein unäres Funktionsobjekt auf Elemente aus einem Bereich
an (Funktionsvorlage)
wendet ein Funktionsobjekt auf die ersten N Elemente einer Sequenz an
(Algorithmus-Funktionsobjekt)
wendet eine Funktion auf einen Bereich von Elementen an
(Algorithmus-Funktionsobjekt)
bereichsbasierte for for-Schleife (C++11)
führt Schleife über Bereich aus