Freigeben über


Bereichsadapter

Bereichsadapter erstellen eine Ansicht (eine der View-Klassen im std::views Namespace) aus einem Bereich. Es wird empfohlen, dass Sie einen Adapter verwenden, um Ansichten zu erstellen, anstatt die Ansichtstypen direkt zu erstellen. Die Adapter sind die beabsichtigte Möglichkeit, auf Ansichten zuzugreifen. Sie sind einfacher zu verwenden, und in einigen Fällen effizienter, als Instanzen der Ansichtstypen direkt zu erstellen.

Eine Ansicht ist ein einfaches Objekt, das auf Elemente aus einem Bereich verweist. Eine Ansicht kann:

  • Bestehen sie nur aus bestimmten Elementen aus einem Bereich.
  • Stellt eine Transformation von Elementen aus einem Bereich dar.
  • Seien Sie umgekehrt von oder nur von den ersten n Elementen eines Bereichs.
  • Seien Sie eine Kombination aus den vorherigen Dingen.

Eine Ansicht ist billig, O(1)zu kopieren, zuzuweisen und zu zerstören - unabhängig davon, wie viele Elemente beteiligt sind. Betrachten Sie das folgende Beispiel:

// requires /std:c++20 or later
#include <ranges>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> input =  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    auto divisible_by_three = [](const int n) {return n % 3 == 0;};
    auto square = [](const int n) {return n * n;};

    auto x = input | std::views::filter(divisible_by_three)
                   | std::views::transform(square);

    for (int i : x)
    {
        std::cout << i << ' ';
    }
}
0 9 36 81

Der erste Bereichsadapter stellt eine Ansicht bereit, filterdie die Elemente enthält, die input durch drei teilbar sind. Der andere Bereichsadapter, nimmt die Ansicht an, transformdie die Elemente enthält, die durch drei divisierbar sind, und bietet eine Ansicht des Quadrats dieser Elemente.

Wenn ein Bereichsadapter eine Ansicht erzeugt, entstehen nicht die Kosten für die Transformation jedes Elements im Bereich, um diese Ansicht zu erzeugen. Die Kosten zum Verarbeiten eines Elements in der Ansicht werden nur bezahlt, wenn Sie auf dieses Element zugreifen.

Das Erstellen einer Ansicht ist vorbereitungsbereit, um in Zukunft zu arbeiten. Im vorherigen Beispiel führt das Erstellen der Ansicht nicht dazu, alle Elemente zu finden, die durch drei elemente dividierbar sind oder diese Elementequadieren. Die Arbeit erfolgt nur, wenn Sie auf ein Element in der Ansicht zugreifen.

Elemente einer Ansicht sind in der Regel die tatsächlichen Elemente des Bereichs, die zum Erstellen der Ansicht verwendet werden. Die Ansicht besitzt in der Regel nicht die Elemente. es bezieht sich nur auf sie, mit Ausnahme von owning_view. Durch Ändern eines Elements wird das Element im Bereich geändert, aus dem die Ansicht erstellt wurde. Das folgende Beispiel zeigt dieses Verhalten:

#include <algorithm>
#include <iostream>
#include <ranges>

int main()
{
    int input[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    auto even = [](const int n) { return n % 2 == 0; };
    auto x = input | std::views::filter(even); // create a view of the even elements from input

    for (int &i : x)
    {
        std::cout << i << ' '; // 0 2 4 6 8 10
    }
    std::cout << '\n'; 

    std::ranges::fill(x, 42); // changes the evens from input[] to 42
    for (int &i : input) // demonstrates that the even elements in the range are modified
    {
        std::cout << i << ' '; // // 42 1 42 3 42 5 42 7 42 9 42
    }
}

Range Adapter kommen in vielen Formen. Beispielsweise gibt es Bereichsadapter, mit denen Sie eine Ansicht erstellen können, indem Sie:

  • Filtern eines anderen Bereichs basierend auf einem Prädikat (filter).
  • Transformieren der Elemente in einem Bereich (transform).
  • Teilen eines Bereichs (split).

Bereichsadapter können miteinander verkettet werden (zusammengesetzt). Hier sind die Leistungsfähigkeit und Flexibilität von Bereichen am deutlichsten. Das Erstellen von Bereichsadaptern ermöglicht es Ihnen, ein Kernproblem mit den vorherigen StL-Algorithmen (Standard Template Library) zu überwinden. Dies ist, dass sie nicht einfach miteinander verkettet werden können.

Die folgenden Bereichsadapter sind im std::views Namespace verfügbar. Der std::views Namespace ist ein Komfortalias für std::ranges::views.

Range Adaptor Beschreibung
allC++20 Erstellen Sie eine Ansicht, die sich auf einen Bereich und dessen Elemente bezieht.
commonC++20 Erstellen Sie eine Ansicht mit denselben Iterator- und Sentineltypen aus einem Bereich, der nicht funktioniert.
countedC++20 Erstellen Sie eine Ansicht der ersten n-Elemente eines Bereichs, beginnend mit der angegebenen Position.
dropC++20 Erstellen Sie eine Ansicht aus einer anderen Ansicht, und überspringen Sie die angegebene Anzahl von Elementen von vorne.
drop_whileC++20 Erstellen Sie eine Ansicht, die die Elemente eines Bereichs enthält, die neu Standard nach den führenden Elementen, die der angegebenen Bedingung entsprechen, gelöscht werden.
elementsC++20 Erstellen Sie eine Ansicht des ausgewählten Indexes in jedem Tupel-ähnlichen Wert in einem Bereich.
emptyC++20 Erstellen Sie eine Ansicht, die keine Elemente enthält.
filterC++20 Erstellen Sie eine Ansicht, die die Elemente eines Bereichs enthält, die der angegebenen Bedingung entsprechen.
iotaC++20 Erstellen Sie eine Ansicht, die eine Abfolge erhöhter Werte enthält.
istreamC++20 Erstellen Sie eine Ansicht über die Elemente eines Datenstroms.
joinC++20 Erstellen Sie eine Ansicht, die alle Elemente mehrerer Bereiche in einer einzelnen Ansicht kombiniert.
keysC++20 Erstellen Sie eine Ansicht des ersten Indexes in jedem Tupel-ähnlichen Wert in einer Auflistung.
lazy_splitC++20 Teilen Sie eine Ansicht auf Der Grundlage eines Trennzeichens in Unterbereiche auf.
reverseC++20 Erstellen Sie eine Ansicht der Elemente eines Bereichs in umgekehrter Reihenfolge.
singleC++20 Erstellen Sie eine Ansicht, die ein Element enthält.
splitC++20 Teilen Sie eine Ansicht auf Der Grundlage eines Trennzeichens in Unterbereiche auf.
takeC++20 Erstellen Sie eine Ansicht der ersten n-Elemente aus einer anderen Ansicht.
take_whileC++20 Erstellen Sie eine Ansicht, die die führenden Elemente eines Bereichs enthält, die der angegebenen Bedingung entsprechen.
transformC++20 Erstellen Sie eine Ansicht der transformierten Elemente aus einer anderen Ansicht.
valuesC++20 Erstellen Sie eine Ansicht des zweiten Indexes in jedem Tupel-ähnlichen Wert in einer Auflistung.

In der vorherigen Tabelle wird ein Bereichsadapter in der Regel so beschrieben, dass er einen Bereich verwendet und eine Ansicht erzeugt. Um genau zu sein, haben Bereichsadapter ein Bereichsargument, das eine der folgenden Akzeptiert:

  • Die cv-unqualified Typmodelle viewund das Argument ist ein Wert oder kann kopiert werden.
  • Wenn Sie das Argument als Wert übergeben, muss es modellieren range und so lange wie die Ansicht leben.
  • Wenn Sie das Argument als Wert übergeben, z. B. beim Aufrufen owning_view, muss es modellieren range und movable.

Range adaptor functions are typically function objects, which look like function calls and enforce constraints on the types that can be passed.

Sie können Bereichsadapter und das Ergebnis von Pipevorgängen (|) an Code übergeben, der Funktionsobjekte erwartet. Im folgenden Beispiel wird die Ansicht, die der split Bereichsadapter erstellt, an den transform Bereichsadapter übergeben, als wäre es durch einen Funktionsaufruf, da der transform Bereichsadapter ein Funktionsobjekt ist.

std::map<int, string> x = {{0, "Hello, world"}, {42, "Goodbye, world"}};
auto y = x | views::values | views::transform(views::split(' '));
// y is a range whose elements are ranges of whitespace-delimited strings from each value in x:
// {{"Hello", "world"}, {"Goodbye", "world"}}

all

Erstellen Sie eine Ansicht aller Elemente in einem Bereich.

template <ranges::viewable_range R>
constexpr ranges::view auto all(R&& rg) const noexcept;

Parameter

R
Der Typ des zugrunde liegenden Bereichs.

rg
Der Bereich, aus dem die Ansicht erstellt werden soll.

Rückgabewert

  • Wenn rg bereits eine Ansicht vorhanden ist, wird eine Kopie von rg.
  • Wenn rg es sich um einen Nicht-Ansichts-Lvalue handelt, bezieht sich ein ref_view Wert, der rgauf . (Die Lebensdauer der Ansicht ist an die Lebensdauer von rg.)
  • Wenn rg es sich um einen Wert ohne Ansicht handelt, z. B. ein temporäres Objekt, oder das Ergebnis der Übergabe des Bereichs an std::move, an ein owning_view.

Dient std::views::all_t<decltype((rg))> zum Abrufen des Typs der zurückgegebenen Ansicht.

Hinweise

Dieser Bereichsadapter ist die beste Möglichkeit, einen Bereich in eine Ansicht zu konvertieren. Ein Grund, eine Ansicht aus einem Bereich zu erstellen, besteht darin, sie nach Wert zu niedrigen Kosten zu übergeben, wenn das Übergeben des Bereichs nach Wert teuer sein könnte.

Das Abrufen einer Ansicht für einen Bereich ist eine nützliche Alternative zum Übergeben eines Schwergewichtsbereichs nach Wert, da Ansichten kostengünstig zum Erstellen, Kopieren und Zerstören sind. Eine mögliche Ausnahme ist owning_vieweine Ansicht, die den zugrunde liegenden Bereich besitzt.

Im Allgemeinen hat O(N) das szenario für die Zerstörung einer Ansicht komplexität für die Anzahl der Elemente im Bereich. Selbst wenn Sie Kopien der Ansicht mit N Elementen zerstörenK, liegt die Gesamtkomplexität immer noch O(N) daran, dass der zugrunde liegende Bereich nur einmal zerstört wird.

Beispiel: all

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
    auto myRefView = std::views::all(v); // create a ref_view of the vector
    std::cout << myRefView.size() << '\n'; // 10

    auto myOwningView = std::views::all(std::move(v)); // create an owning_view from a moved vector
    std::cout << myRefView.size() << '\n'; // outputs 0 because myOwningView now owns the elements
    std::cout << v.size() << '\n'; // outputs 0 because myOwningView now owns the elements
    std::cout << myOwningView.size(); // 10 
}
10
0
0
10

common

Erstellen Sie eine Ansicht mit demselben Anfangs iterator- und Sentineltyp aus einem Bereich, der möglicherweise nicht vorhanden ist.

template <ranges::viewable_range R>
constexpr ranges::view auto common(R&& rg) const noexcept;

Parameter

R
Der Typ des zugrunde liegenden Bereichs.

rg
Der Bereich, aus dem die Ansicht erstellt werden soll.

Rückgabewert

  • views::all(rg) wenn rg es sich um einen Bereich mit demselben Iterator- und Sentineltyp handelt.
  • common_view(views::all(rg)) wenn rg unterschiedliche Iterator- und Sentineltypen vorhanden sind.

Hinweise

Wenn für eine API der Start-Iterator und end sentinel denselben Typ aufweisen müssen und die von Ihnen verwendete Ansicht diese Anforderung nicht erfüllt (oder Sie wissen nicht, ob dies der Fall ist), verwenden Sie diesen Bereichsadapter, um einen common_view. Es garantiert, dass der Typ des Anfangs iterators und der Typ des End-Sentinels identisch sind.

Beispiel: common

// requires /std:c++20 or higher
#include <ranges>
#include <iostream>
#include <numeric>
#include <list>

int main()
{
    std::list<int> lst{1, 2, 3, 4, 5, 6, 7, 8, 9};

    auto firstFive = std::views::take(lst, 5); 
    // firstFive.begin(), firstFive.end() have different types: counted_iterator versus default_sentinel
    // auto r = std::accumulate(firstFive.begin(), firstFive.end(), 0); // Error: accumulate() requires firstFive.begin() and firstFive.end() types to be the same.
    
    auto common = std::views::common(firstFive); // create a common_view that has the same begin/end iterator types
    std::cout << std::accumulate(common.begin(), common.end(), 0); // Now you can call the API because the iterator types are the same. Outputs 15 (1+2+3+4+5) 
}
15

counted

Erstellen Sie eine Ansicht der ersten count Elemente eines Bereichs, beginnend mit der angegebenen Position.

template<class Iterator>
constexpr auto counted(Iterator&& it, iter_difference_t<Iterator> count);

Parameter

DifferenceType
Der Typ der Anzahl.

Iterator
Der Typ des Iterators.

count
Die Anzahl der Elemente, die in die Ansicht einbezogen werden sollen. Muss nicht negativ sein.

  • Wenn count == 0, wird ein leerer span Wert zurückgegeben.
  • Wenn count die Anzahl der Elemente im Bereich größer ist, ist das Verhalten nicht definiert.

it
Ein Iterator für das Element im Bereich, mit dem begonnen werden soll. Das Element, auf das der Iterator verweist, ist in der erstellten Ansicht enthalten.

Rückgabewert

A span wird zurückgegeben, wenn it es sich um arrays contiguous_iterator , Vektoren und andere Container handelt, die ihre Elemente zusammenhängend speichern. Andernfalls wird ein subrange Wert zurückgegeben.

Hinweise

Die enthaltenen Elemente sind [it, count).

Nachdem die Ansicht erstellt wurde, bleibt die Anzahl der Elemente in der Ansicht gleich, auch wenn der Bereich, aus dem sie erstellt wurde, geändert wurde. Wenn sich der zugrunde liegende Bereich ändert, kann der Zugriff auf Elemente aus der Ansicht jedoch zu nicht definierten Verhaltensweisen führen.

Beispiel: counted

// requires /std:c++20 or later
#include <algorithm>
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    auto pos5 = std::ranges::find(v, 5);
    auto countedView = std::views::counted(pos5, 5);
    for (auto e : countedView) // outputs 5 6 7 8 9
    {
        std::cout << e << ' ';
    }
    std::cout << '\n';

    // You can pass the range directly if it supports input_or_output_iterator, in which case
    // the count starts from the first element
    const char chars[] = { 'H','i',' ','t','h','e','r','e' };
    for (char c : std::views::counted(chars, 2))
    {
        std::cout << c; // outputs Hi
    }
}
5 6 7 8 9
Hi

drop

Erstellen Sie eine Ansicht, die die ersten n Elemente eines Bereichs ausschließt.

1) template<ranges::viewable_range R>
constexpr ranges::view auto drop(R&& rg, ranges::range_difference_t<R> count);

2) template<class DifferenceType>
constexpr /* range closure object */ drop(DifferenceType&& count);

Parameter

DifferenceType
Der Typ, der die Anzahl der zu überspringenden Elemente beschreibt.

count
Die Anzahl der Elemente, die von vorne rgabzulegen sind. Muss nicht negativ sein.

  • Wenn count == 0alle Elemente rg zurückgegeben werden.
  • Wenn count die Anzahl der Elemente größer rgist, wird eine leere Ansicht zurückgegeben.

R
Der Typ des Bereichs.

rg
Der Bereich, der zum Erstellen der Ansicht verwendet wird.

Rückgabewert

Eine Ansicht des zugrunde liegenden Bereichs mit der angegebenen Anzahl von Elementen, die von vorne abgelegt wurden.

Wenn Sie mehr Elemente angeben, die abzulegen sind, als im zugrunde liegenden Bereich vorhanden sind, wird ein empty_view Wert zurückgegeben.

Die zurückgegebene Ansicht ist in der Regel, aber nicht immer, eine Spezialisierung von drop_view. Dies bedeutet:

Hinweise

Nachdem sie erstellt wurde, bleibt die Anzahl der Elemente in der Ansicht unverändert, auch wenn die Ansicht, die sie aus Änderungen erstellt wurde. Wenn sich die zugrunde liegende Ansicht ändert, kann der Zugriff auf Elemente in der zurückgegebenen Ansicht jedoch zu einem nicht definierten Verhalten führen.

drop ist das Gegenteil von take.

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | drop(5). Sie kann auch mit Funktionsaufrufsyntax verwendet werden: drop(collection, 5) oder drop(5)(collection).

Beispiel: drop

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{1, 2, 3, 4, 5};
    auto newView = std::views::drop(v, 3);
    for (auto e : newView) // 4 5
    {
        std::cout << e << ' ';
    }
    std::cout << '\n';

    auto numbers = std::views::iota(0) | std::views::take(10); // build a view of 10 integers
    auto latterHalf = numbers | std::views::drop(5);
    for (auto i : latterHalf)
    {
        std::cout << i << ' '; // 5 6 7 8 9
    }
}
4 5
5 6 7 8 9

drop_while

Erstellen Sie eine Ansicht, die die Elemente eines Bereichs enthält, die neu Standard nach den führenden Elementen, die der angegebenen Bedingung entsprechen, gelöscht werden.

1) template<ranges::viewable_range R, class P>
constexpr ranges::view auto drop_while(R&& rg, P&& predicate);

2) template<class P>
constexpr /*range adaptor closure*/ drop_while(P&& predicate);

Parameter

R
Der Typ des Bereichs.

predicate
Die Bedingungen, die bestimmen, welche führenden Elemente aus dem Bereich entfernt werden sollen.

rg
Der zugrunde liegende Bereich, aus dem die Ansicht erstellt werden soll.

Rückgabewert

A drop_while_view that consists of the elements that re Standard when the leading elements that match the predicate are dropped.

Hinweise

Beendet das Ablegen von rg Elementen, sobald das Prädikat zurückgegeben wird false.

drop_while ist das Gegenteil von take_while.

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | drop_while(predicate). Sie kann auch mit Funktionsaufrufsyntax verwendet werden: drop_while(collection, predicate) oder drop_while(predicate)(collection).

Beispiel: drop_while

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
    auto myView = std::views::drop_while(
        v,
        [](int i) {return i >= 0; });
    print(myView); // -4 5 6

    auto myView2 = v | std::views::drop_while(
        [](int i) {return i < 5; });
    print(myView2); // 5 6
}
-4 5 6
5 6

elements

Erstellen Sie eine elements_viewAnsicht des ausgewählten Indexes in jedem Tupel-ähnlichen Wert in einem Bereich. Erstellen Sie z. B. bei einem Wertebereich std::tuple<string, int> ein elements_view Element aller string Elemente aus jedem Tupel.

template<ranges::viewable_range R, size_t N>
constexpr ranges::view auto elements<N>(R&& rg);

Parameter

N
Der Index des Elements, das aus jedem Tupel-ähnlichen Wert ausgewählt werden soll, der in die Ansicht eingeschlossen werden soll.

R
Der Typ des zugrunde liegenden Bereichs.

rg
Der Bereich der Tupel-ähnlichen Werte, aus der die Ansicht erstellt werden soll.

Rückgabewert

Ein elements_view Wert, der aus dem ausgewählten Index in jedem Tupel-ähnlichen Wert in einer Auflistung besteht.

Beispiel: elements

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>

int main()
{
    std::map<std::string, int> cpp_standards
    {
        {"C++98", 1998},
        {"C++03", 2003},
        {"C++11", 2011},
        {"C++14", 2014},
        {"C++17", 2017},
        {"C++20", 2020}
    };

    // Create an elements_view of all the string elements from each tuple
    for (int const year : std::views::elements<1>(cpp_standards))
    {
        std::cout << year << ' '; // 2003 2011 2014 2017 1998 2020
    }
    std::cout << '\n';

    // Another way, using |: create an elements_view of all the int elements from each tuple
    for (auto&& name : cpp_standards | std::views::elements<0>)
    {
        std::cout << name << ' '; // C++03 C++11 C++14 C++17 C++98 c++20
    }
}
2003 2011 2014 2017 1998 2020
C++03 C++11 C++14 C++17 C++98 c++20

empty

Erstellen Sie eine empty_viewAnsicht, die keine Elemente enthält.

template<class T>
inline constexpr empty_view<T> empty{};

Parameter

T
Der Typ der Elemente in der Ansicht. Die Ansicht benötigt einen Elementtyp, obwohl keine Elemente vorhanden sind.

Rückgabewert

empty_view.

Hinweise

Dies empty_view kann hilfreich sein, wenn Sie Code aufrufen, der eine Ansicht erfordert, aber keine der zugehörigen Elemente verarbeiten muss.

Beispiel: empty

// requires /std:c++20 or higher
#include <ranges>
#include <iostream>

int main()
{
    auto anEmptyView = std::views::empty<int>;
    bool isNotEmpty = (bool)anEmptyView;
    std::cout << boolalpha << isNotEmpty << "\n"; // false
}
false

filter

Erstellen Sie eine Ansicht, die die Elemente eines Bereichs enthält, die der angegebenen Bedingung entsprechen.

1) template<ranges::viewable_range R, class P>
    requires {filter_view(forward<R>(rg), forward<P>(predicate));}
constexpr ranges::view auto filter(R&& rg, P&& predicate);

2) template<class P>
constexpr /*range adaptor closure*/ filter(P&& predicate);

Parameter

P
Der Typ des Prädikats.

predicate
Die Bedingungen, die bestimmen, welche Elemente im Bereich beibehalten werden sollen.

R
Der Typ des zugrunde liegenden Bereichs.

rg
Der Bereich, aus dem die Ansicht erstellt werden soll.

Rückgabewert

A filter_view , das die Elemente eines Bereichs enthält, die dem Prädikat entsprechen.

Hinweise

Um effizienzwirksam zu sein, führen Sie bei Verwendung filter und transform zusammen mit einem Rohr |zuerst die filtertransform Elemente aus, die Sie behalten möchten.

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | filter(predicate). Sie kann auch mit Funktionsaufrufsyntax verwendet werden: filter(collection, predicate) oder filter(predicate)(collection).

Beispiel: filter

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> v{0, 1, 2, 3, -4, 5, 6};
    auto myView = std::views::filter(v, [](int i) {return i < 5; });
    print(myView); // 0 1 2 3 -4

    auto myView2 = v | std::views::filter([](int i) {return i < 5; }); // pipe syntax
    print(myView2); // 0 1 2 3 -4
}
0 1 2 3 -4
0 1 2 3 -4

iota

Erstellen Sie eine Ansicht, die eine Abfolge erhöhter Werte enthält. Die Sequenz kann gebunden werden oder nicht.

template<class V>
constexpr ranges::view auto iota(V&& startValue); // create an unbounded sequence of incrementing values

template<class V, class E>
constexpr ranges::view auto iota(V&& startValue, E&& endValue); // create a bounded sequence of incrementing values

Parameter

E
Der Typ des Endwerts.

S
Der Typ des Startwerts.

startValue
Der erste Wert in der Sequenz.

endValue
Dieser Wert liegt über dem letzten Wert, der sich in der Sequenz befindet. Generiert z. B. eine Ansicht mit std::views::iota(0, 5) den Werten 0,1,2,3,4.

Rückgabewert

Eine iota_view Abfolge von steigenden Werten.

Hinweise

Bei einer ungebundenen Sequenz wird das Verhalten nicht definiert, nachdem der Maximalwert seines Datentyps erreicht wurde.

Beispiel: iota

// requires /std:c++20 or later
#include <ranges>
#include <iostream>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    // create an iota view with its range adaptor (preferred)
    print(std::views::iota(0, 5)); // outputs 0 1 2 3 4
    
    // create an iota_view class directly
    std::ranges::iota_view letters{'a', 'f'};
    print(letters); // a b c d e
}
0 1 2 3 4
a b c d e

istream

Erstellen Sie eine Ansicht über die Elemente eines Datenstroms.

template <class Val>
views::istream<Val>(str);

Parameter

str
Ein Streamobjekt. Sein Typ wird von einer Spezialisierung von std::basic_istreamabgeleitet.

Val
Der Typ der Elemente, die aus dem Datenstrom extrahiert werden sollen.

Rückgabewert

einen basic_istream_view

Dieser Bereichsadapter entspricht ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str)dem U Typ des Bereichs str.

Beispiel: istream

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <sstream>
#include <vector>

int main()
{
    std::istringstream doubles{"1.1 2.2 3.3 4.4 5.5"};
    for (const auto& elem : std::views::istream<double>(doubles))
    {
        std::cout << elem << ' '; // 1.1 2.2 3.3 4.4 5.5
    }
}
1.1 2.2 3.3 4.4 5.5

join

Erstellen Sie eine Ansicht, die alle Elemente mehrerer Bereiche in einer einzelnen Ansicht kombiniert.

1) template <ranges::viewable_range R>
[[nodiscard]] constexpr ranges::view auto join(R&& rg) const noexcept;

2) inline constexpr /*range adaptor closure*/ join();

Parameter

R
Der Typ des zugrunde liegenden Bereichs.

rg
Der Bereich, aus dem die Ansicht erstellt werden soll.

Rückgabewert

A join_view , das die Elemente aller Bereiche im zugrunde liegenden Bereich enthält.

Beispiel: join

#include <iostream>
#include <vector>
#include <ranges>
#include <string>

int main()
{
    // a range of two ranges
    std::vector<std::string> rangeOfRanges[2]{{"C++20", "contains:"}, {"ranges", "modules", "concepts & more."}};

    for (const auto& elem : std::views::join(rangeOfRanges))
    {
        std::cout << elem << ' ';
    }
}
C++20 contains: ranges modules concepts & more.

Hinweise

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | join. Sie kann auch mit Funktionsaufrufssyntax verwendet werden: join(collection).

keys

Erstellen Sie einen keys_view des ersten Indexes in jedem Tupel-ähnlichen Wert in einer Auflistung. Dies ist nützlich, um Schlüssel aus assoziativen Containern zu extrahieren. Erstellen Sie beispielsweise in einem Bereich std::tuple<string, int>von , eine Ansicht, die string aus allen Elementen aus jedem Tupel besteht.

template <ranges::viewable_range R>
constexpr auto keys(R&& rg);

Parameter

R
Der Typ des zugrunde liegenden Bereichs.

Rückgabewert

A keys_view , das aus dem ersten Index in jedem Tupel-ähnlichen Wert im Bereich besteht.

Beispiel: keys

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>

int main()
{
    // ========== extract keys from a map

    std::map<std::string, int> cpp_standards
    {
        {"C++98", 1998},
        {"C++03", 2003},
        {"C++11", 2011},
        {"C++14", 2014},
        {"C++17", 2017},
        {"C++20", 2020}
    };

    // Extract all of the keys from the map
    for (std::string standards : std::views::keys(cpp_standards))
    {
        std::cout << standards << ' '; // C++03 C++11 C++14 C++17 C++98 C++20
    }
    std::cout << '\n';

    // ========== Extract keys from a pair

    std::vector<std::pair<std::string, int>> windows
    {
        {"Windows 1.0", 1985},
        {"Windows 2.0", 1987},
        {"Windows 3.0", 1990},
        {"Windows 3.1", 1992},
        {"Windows NT 3.1", 1993},
        {"Windows 95", 1995},
        {"Windows NT 4.0", 1996},
        {"Windows 95", 1995},
        {"Windows 98", 1998},
        {"Windows 1.0", 1985},
        {"Windows 2000", 2000}
    };
    
    // Another way to call the range adaptor is by using '|'
    for (std::string version : windows | std::views::keys)
    {
        std::cout << version << ' '; // Windows 1.0 Windows 2.0 Windows 3.0 ...
    }
}
C++03 C++11 C++14 C++17 C++98 C++20
Windows 1.0 Windows 2.0 Windows 3.0 Windows 3.1 Windows NT 3.1 Windows 95 Windows NT 4.0 Windows 95 Windows 98 Windows 1.0 Windows 2000

lazy_split

Aufteilen eines Bereichs in Unterbereiche basierend auf einem Trennzeichen. Das Trennzeichen kann ein einzelnes Element oder eine Ansicht von Elementen sein.

1) template<viewable_range R, class Pattern>
constexpr view auto lazy_split(R&& rg, Pattern&& delimiter);

2) template<class Pattern>
constexpr /*range adaptor closure*/ lazy_split(Pattern&& delimiter);

Parameter

delimiter
Ein einzelner Wert oder eine Abfolge von Werten, die angeben, wo der Bereich geteilt werden soll.

Pattern
Der Typ des Trennzeichens.

R
Der Typ des bereichs, der geteilt werden soll.

rg
Der bereich, der geteilt werden soll.

Rückgabewert

Eine lazy_split_view , die einen oder mehrere Unterbereiche enthält und das Ergebnis der Aufteilung des ursprünglichen Bereichs auf delimiterist.

Hinweise

Das Trennzeichen ist nicht Teil des Ergebnisses. Wenn Sie den Bereich 1,2,3 beispielsweise auf den Wert 2aufteilen, erhalten Sie zwei Unterbereiche: 1 und 3.

Ein verwandter Adapter ist split. Die wichtigsten Unterschiede zwischen [split_view](split-view-class.md) and lazy_split_view' sind:

Sicht Kann einen const Bereich teilen Bereichs iterator
split_view Nein Unterstützt forward_range oder höher
lazy_split_view ja input_range oder höher

Bevorzugen Sie split_view es, da sie effizienter ist, es sei denn, Sie müssen einen Bereich teilen, der lautet const.

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | lazy_split(delimiter). Sie kann auch mit Funktionsaufrufsyntax verwendet werden: lazy_split(collection, delimiter) oder lazy_split(delimiter)(collection).

Beispiel: lazy_split

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> rg{1, 2, 3, 1, 2, 3, 4, 5, 6};

    // split on a single element
    for (const auto& sub : rg | std::views::split(3))
    {
        // outputs:
        // 1 2
        // 1 2
        // 4 5 6
        for (const auto& elem : sub)
        {
            std::cout << elem << ' ';
        }
        std::cout << '\n';
    }

    // split on a sequence of elements
    int delimiters[] = {2, 3};
    for (const auto& subrange : std::views::split(rg, delimiters))
    {
        // outputs 1 1 4 5 6
        for (auto& i : subrange)
        {
            std::cout << i << " ";
        }
    }
}
1 2
1 2
4 5 6
1 1 4 5 6

reverse

Erstellen Sie eine Ansicht der Elemente eines Bereichs in umgekehrter Reihenfolge.

1) template<viewable_range R>
constexpr ranges::view auto reverse(R&& rg);

2) inline constexpr /*range adaptor closure*/ reverse();

Parameter

R
Der Typ des zugrunde liegenden Bereichs, der umgekehrt werden soll.

rg
Der bereich, der umgekehrt werden soll.

Rückgabewert

Eine Ansicht, die die Elemente des zugrunde liegenden Bereichs in umgekehrter Reihenfolge darstellt. Die zurückgegebene Ansicht ist in der Regel, aber nicht immer, eine Spezialisierung von reverse_view. Dies bedeutet:

  • Wenn V es sich um eine Spezialisierung handelt reverse_view, ist das Ergebnis die zugrunde liegende Ansicht des Arguments. Ein Doppelrücklauf ist ein No-Op (kein Vorgang).
  • Wenn V das Formular subrange<reverse_iterator<I>, reverse_iterator<I>>vorhanden ist, ist das Ergebnis eines subrange der entwrappten Iteratoren. Ein Doppelkehrer ist ein No-Op.
  • Andernfalls ist das Ergebnis ein reverse_view.

Hinweise

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | reverse. Sie kann auch mit Funktionsaufrufssyntax verwendet werden: reverse(collection).

Beispiel: reverse

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
    auto rv = v | std::views::reverse; // using the pipe syntax  

    for (auto &&e : rv) // outputs 6 5 -4 3 2 1 0
    {
        std::cout << e << ' ';
    }
    std::cout << '\n';

    // using the range adaptor without using the pipe syntax
    auto rv2 = std::views::reverse(v);
    for (auto &&e : rv2) // outputs 6 5 -4 3 2 1 0
    {
        std::cout << e << ' ';
    }
}
6 5 -4 3 2 1 0
6 5 -4 3 2 1 0

single

Erstellen Sie eine single_viewAnsicht, die ein Element enthält.

template<class T>
constexpr ranges::view auto single(T&& t);

Parameter

T
Der Typ des Elements in der Ansicht.

t
Der Wert des Elements, das in der Ansicht gespeichert werden soll.

Rückgabewert

Eine single_view , die enthält t.

Hinweise

Diese Ansicht ist für Testzwecke nützlich, um Code aufzurufen, der mit einer Ansicht bereitgestellt werden muss, die mindestens ein Element enthält.

Beispiel: single

// requires /std:c++20 or higher
#include <ranges>
#include <string>
#include <tuple>
#include <iostream>

int main()
{
    auto sv = std::views::single(7);
    std::cout << sv.front() << " " << *sv.data() << "\n"; // 7 7
    
    auto sv2 = std::views::single(<std::tuple<double, std::string>{6502, "8-bit"});
    std::cout << std::get<0>(sv2[0]) << " " << std::get<1>(sv2[0]) << "\n"; // 6502 8-bit
}
7 7
6502 8-bit

split

Teilen Sie eine Ansicht auf Der Grundlage eines Trennzeichens in Unterbereiche auf. Das Trennzeichen kann ein einzelnes Element oder eine Abfolge von Elementen sein.

1) template<viewable_range R, class Pattern>
constexpr view auto split(R&& rg, Pattern&& delimiter);

2) template<class Pattern>
constexpr /*range adaptor closure*/ split(Pattern&& delimiter);

Parameter

delimiter
Ein einzelner Wert oder eine Abfolge von Werten, die angeben, wo der Bereich geteilt werden soll.

Pattern
Der Typ des Trennzeichens.

R
Der Typ des zugrunde liegenden Bereichs, der geteilt werden soll.

rg
Der bereich, der geteilt werden soll.

Rückgabewert

A split_view , das eine oder mehrere Unterbereiche enthält.

Hinweise

Das Trennzeichen ist nicht Teil des Ergebnisses. Wenn Sie den Bereich 1,2,3 beispielsweise auf den Wert 2aufteilen, erhalten Sie zwei Unterbereiche: 1 und 3.

Ein verwandter Adapter ist lazy_split. Die wichtigsten Unterschiede zwischen split_view und lazy_split_view sind:

Sicht Kann einen const Bereich teilen Bereichstyp
split_view Nein Unterstützt forward_range oder höher
lazy_split_view ja Unterstützt input_range oder höher

Bevorzugen Sie split_view es, da sie effizienter ist, es sei denn, Sie müssen einen Bereich teilen, der lautet const.

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | split(delimiter). Sie kann auch mit Funktionsaufrufsyntax verwendet werden: split(collection, 5) oder split(5)(collection).

Beispiel: split

// requires /std:c++20 or later
#include <ranges>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> rg{ 1, 2, 3, 1, 2, 3, 4, 5, 6 };

    // split on a single element, 3
    for (const auto& sub : rg | std::views::split(3))
    {
        // This prints out:
        // 1,2
        // 4,5,6
        for (const auto& elem : sub)
        {
            std::cout << elem << ' ';
        }
        std::cout << '\n';
    }

    // split on a sequence of elements, 2,3
    int delimiters[] = {2, 3};
    for (const auto& subrange : std::views::split(rg, delimiters))
    {
        // outputs 1 1 4 5 6
        for (auto& i : subrange)
        {
            std::cout << i << " ";
        }
    }
}
1 2
1 2
4 5 6
1 1 4 5 6

take

Erstellen Sie eine Ansicht, die die angegebene Anzahl von Elementen enthält, die von der Vorderseite eines Bereichs stammen.

1) template<ranges::viewable_range R>
constexpr ranges::view auto take(R&& rg, ranges::range_difference_type<R> count);

2) template<class DifferenceType>
constexpr /*range adaptor closure*/ take(DifferenceType&& count); 

Parameter

R
Der Typ des zugrunde liegenden Bereichs.

rg
Der Bereich, aus dem die Ansicht erstellt werden soll.

count
Die Anzahl der Elemente, die von vorne rgentnommen werden sollen.

Rückgabewert

Die zurückgegebene Ansicht ist in der Regel, aber nicht immer, eine Spezialisierung von take_view. Speziell:

Hinweise

Wenn Sie mehr elemente angeben, die als vorhanden sind rg, werden alle Elemente übernommen.

take ist das Gegenteil von drop.

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | take(5). Sie kann auch mit Funktionsaufrufsyntax verwendet werden: take(5, collection) oder take(5)(collection).

Beispiel: take

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::string s{ "abcdefg" };
    auto myView = std::views::take(s, 3);
    for (auto c : myView)
    {
        std::cout << c << ' '; // a b c
    }

    std::cout << std::endl;

    for (auto c : s | std::views::take(3)) // pipe syntax
    {
        std::cout << c << ' '; // a b c
    }
}
a b c
a b c

take_while

Erstellen Sie eine Ansicht, die die führenden Elemente eines Bereichs enthält, die der angegebenen Bedingung entsprechen.

1) template<ranges::viewable_range R, class P>
constexpr ranges::view auto take_while(R&& rg, P&& predicate);

2) template<class P>
constexpr /*range adaptor closure*/ take_while(P&& predicate);

Parameter

P
Der Typ des Prädikats.

predicate
Die Bedingungen, die bestimmen, welche führenden Elemente aus dem Bereich kopiert werden sollen.

R
Der Typ des zugrunde liegenden Bereichs.

rg
Der Bereich, aus dem die Ansicht erstellt werden soll.

Rückgabewert

Ein take_while_view Element, das aus den ersten count Elementen besteht, die den angegebenen Kriterien im Bereich entsprechen.

Hinweise

Beendet das Übernehmen von Elementen, rg nachdem das Prädikat zurückgegeben false wurde oder der Bereich nicht mehr elemente enthält.

take_while ist das Gegenteil von drop_while.

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | take_while(pred). Sie kann auch mit Funktionsaufrufsyntax verwendet werden: take_while(collection, pred) oder take_while(pred)(collection).

Beispiel: take_while

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
    auto myView = std::views::take_while(
        v, [](int i) {return i >= 0; });
    print(myView); // 0 1 2 3

    print(v | std::views::take_while( // 0 1 2 3 -4
        [](int i) {return i < 5; })); // pipe syntax
}
0 1 2 3
0 1 2 3 -4

transform

Erstellen Sie eine Ansicht von Elementen, von denen jede eine Transformation eines Elements im angegebenen Bereich ist.

1) template<viewable_range R, class F>
constexpr ranges::view auto transform(R&& rg, F&& fun);

2) template<class F>
constexpr /*range adaptor closure*/ transform(F&& fun);

Parameter

F
Der Typ des Funktionsobjekts zum Transformieren der Elemente.

R
Der Typ des zugrunde liegenden Bereichs.

fun
Die Funktion, die die Elemente transformiert.

rg
Der Bereich, aus dem die Ansicht erstellt werden soll.

Rückgabewert

A transform_view , das die transformierten Elemente von rg.

Hinweise

Um effizienzwirksam zu sein, führen Sie beim Verfassen filter und transform, zuerst die filter Elemente transform aus, die Sie behalten möchten.

Der code, der weiter oben als "2)" gezeigt wurde, kann mit Pipesyntax verwendet werden: collection | transform(fun). Sie kann auch mit Funktionsaufrufsyntax verwendet werden: transform(collection, fun) oder transform(fun)(collection).

Beispiel: transform

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

void print(auto&& v)
{
    for (auto&& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<int> v{0, 1, 2, 3, -4, 5, 6};
    auto myView = std::views::transform(v, [](int i) {return i * 2; });
    print(myView); // 0 2 4 6 -8 10 12

    print(v | std::views::transform( // 0 2 4 6 -8 10 12
        [](int i) {return i * 2; })); // pipe syntax
}
0 2 4 6 -8 10 12
0 2 4 6 -8 10 12

values

Erstellen Sie ein values_view Objekt, das aus dem zweiten Index in jedem Tupel-ähnlichen Wert in einer Auflistung besteht. Dies ist nützlich, um eine Ansicht der Werte in einem assoziativen Container zu erstellen. Erstellen Sie beispielsweise bei einem Wertebereich std::tuple<string, int> eine Ansicht, die int aus allen Elementen aus jedem Tupel besteht.

template <range::viewable_range R>
constexpr ranges::view auto values(R&& rg);

Parameter

R
Der Typ des zugrunde liegenden Bereichs.

rg
Der zugrunde liegende Bereich von Tupel-ähnlichen Werten.

Rückgabewert

Ein values_view aus dem zweiten Index in jedem Tupel-ähnlichen Wert im Bereich.

Beispiel: values

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>

int main()
{
    // ========== working with a map

    std::map<std::string, int> cpp_standards
    {
        {"C++98", 1998},
        {"C++03", 2003},
        {"C++11", 2011},
        {"C++14", 2014},
        {"C++17", 2017},
        {"C++20", 2020}
    };

    // Extract all of the years from the map
    for (int years : std::views::values(cpp_standards))
    {
        std::cout << years << ' '; // 2003 2011 2014 2017 1998 2020
    }
    std::cout << '\n';

    // ========== working with pairs

    std::vector<std::pair<std::string, int>> windows
    {
        {"Windows 1.0", 1985},
        {"Windows 2.0", 1987},
        {"Windows 3.0", 1990},
        {"Windows 3.1", 1992},
        {"Windows NT 3.1", 1993},
        {"Windows 95", 1995},
        {"Windows NT 4.0", 1996},
        {"Windows 95", 1995},
        {"Windows 98", 1998},
        {"Windows 1.0", 1985},
        {"Windows 2000", 2000}
    };

    // Another way to call the range adaptor by using '|'
    // Create a values_view that contains the year from each pair
    for (int years : windows | std::views::values)
    {
        std::cout << years << ' '; // 1985 1987 1990 1992 ...
    }
}
2003 2011 2014 2017 1998 2020
1985 1987 1990 1992 1993 1995 1996 1995 1998 1985 2000

Bereichsadaptertypaliasen

all_t

Stellt den Typ der zurückgegebenen Ansicht all bereit.

template <ranges::viewable_range R>
using all_t = decltype(views::all(std::declval<R>()));

Parameter

R
Der Typ des zugrunde liegenden Bereichs.

Rückgabewert

Der Typ der zurückgegebenen Ansicht all : decltype(views::all(std::declval<R>())).

Beispiel: all_t

#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
    auto myView = std::views::all(v);
    std::views::all_t<decltype((v))> &viewType = myView;
}

Siehe auch

<ranges>
<ranges> Konzepte
Anzeigen von Klassen