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, filter
die die Elemente enthält, die input
durch drei teilbar sind. Der andere Bereichsadapter, nimmt die Ansicht an, transform
die 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 |
---|---|
all C++20 |
Erstellen Sie eine Ansicht, die sich auf einen Bereich und dessen Elemente bezieht. |
common C++20 |
Erstellen Sie eine Ansicht mit denselben Iterator- und Sentineltypen aus einem Bereich, der nicht funktioniert. |
counted C++20 |
Erstellen Sie eine Ansicht der ersten n-Elemente eines Bereichs, beginnend mit der angegebenen Position. |
drop C++20 |
Erstellen Sie eine Ansicht aus einer anderen Ansicht, und überspringen Sie die angegebene Anzahl von Elementen von vorne. |
drop_while C++20 |
Erstellen Sie eine Ansicht, die die Elemente eines Bereichs enthält, die verbleiben, nachdem die führenden Elemente, die der angegebenen Bedingung entsprechen, gelöscht werden. |
elements C++20 |
Erstellen Sie eine Ansicht des ausgewählten Indexes in jedem Tupel-ähnlichen Wert in einem Bereich. |
empty C++20 |
Erstellen Sie eine Ansicht, die keine Elemente enthält. |
filter C++20 |
Erstellen Sie eine Ansicht, die die Elemente eines Bereichs enthält, die der angegebenen Bedingung entsprechen. |
iota C++20 |
Erstellen Sie eine Ansicht, die eine Abfolge erhöhter Werte enthält. |
istream C++20 |
Erstellen Sie eine Ansicht über die Elemente eines Datenstroms. |
join C++20 |
Erstellen Sie eine Ansicht, die alle Elemente mehrerer Bereiche in einer einzelnen Ansicht kombiniert. |
keys C++20 |
Erstellen Sie eine Ansicht des ersten Indexes in jedem Tupel-ähnlichen Wert in einer Auflistung. |
lazy_split C++20 |
Teilen Sie eine Ansicht auf Der Grundlage eines Trennzeichens in Unterbereiche auf. |
reverse C++20 |
Erstellen Sie eine Ansicht der Elemente eines Bereichs in umgekehrter Reihenfolge. |
single C++20 |
Erstellen Sie eine Ansicht, die ein Element enthält. |
split C++20 |
Teilen Sie eine Ansicht auf Der Grundlage eines Trennzeichens in Unterbereiche auf. |
take C++20 |
Erstellen Sie eine Ansicht der ersten n-Elemente aus einer anderen Ansicht. |
take_while C++20 |
Erstellen Sie eine Ansicht, die die führenden Elemente eines Bereichs enthält, die der angegebenen Bedingung entsprechen. |
transform C++20 |
Erstellen Sie eine Ansicht der transformierten Elemente aus einer anderen Ansicht. |
values C++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
Typmodelleview
und 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 modellierenrange
undmovable
.
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 vonrg
. - Wenn
rg
es sich um einen Nicht-Ansichts-Lvalue handelt, bezieht sich einref_view
Wert, derrg
auf . (Die Lebensdauer der Ansicht ist an die Lebensdauer vonrg
.) - Wenn
rg
es sich um einen Wert ohne Ansicht handelt, z. B. ein temporäres Objekt, oder das Ergebnis der Übergabe des Bereichs anstd::move
, an einowning_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_view
eine 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)
wennrg
es sich um einen Bereich mit demselben Iterator- und Sentineltyp handelt.common_view(views::all(rg))
wennrg
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 leererspan
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 rg
abzulegen sind. Muss nicht negativ sein.
- Wenn
count == 0
alle Elementerg
zurückgegeben werden. - Wenn
count
die Anzahl der Elemente größerrg
ist, 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:
- Wenn
V
es sich um eine Spezialisierung vonempty_view
, oder eine Spezialisierung vonspan
,basic_string_view
, ,iota_view
odersubrange
das ist beiderandom_access_range
undsized_range
, ist das Ergebnis eine Spezialisierung vonV
. - Andernfalls ist das Ergebnis
drop_view
.
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 verbleiben, nachdem die führenden Elemente, 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
Ein drop_while_view
Element, das aus den Elementen besteht, die verbleiben, wenn die führenden Elemente, die mit dem Prädikat übereinstimmen, abgelegt werden.
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_view
Ansicht 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_view
Ansicht, 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
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 filter
transform
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_istream
abgeleitet.
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 delimiter
ist.
Hinweise
Das Trennzeichen ist nicht Teil des Ergebnisses. Wenn Sie den Bereich 1,2,3
beispielsweise auf den Wert 2
aufteilen, 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:
Ansicht | 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 handeltreverse_view
, ist das Ergebnis die zugrunde liegende Ansicht des Arguments. Ein Doppelrücklauf ist ein No-Op (kein Vorgang). - Wenn
V
das Formularsubrange<reverse_iterator<I>, reverse_iterator<I>>
vorhanden ist, ist das Ergebnis einessubrange
der entwrappten Iteratoren. Ein Doppelkehrer ist ein No-Op. - Andernfalls ist das Ergebnis
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_view
Ansicht, 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 2
aufteilen, erhalten Sie zwei Unterbereiche: 1
und 3
.
Ein verwandter Adapter ist lazy_split
. Die wichtigsten Unterschiede zwischen split_view
und lazy_split_view
sind:
Ansicht | 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 rg
entnommen werden sollen.
Rückgabewert
Die zurückgegebene Ansicht ist in der Regel, aber nicht immer, eine Spezialisierung von take_view
. Speziell:
- Wenn
V
es sich um eine Spezialisierung vonempty_view
, oder eine Spezialisierung vonspan
,basic_string_view
, ,iota_view
odersubrange
das ist beiderandom_access_range
undsized_range
, ist das Ergebnis eine Spezialisierung vonV
. - Andernfalls ist das Ergebnis
take_view
.
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;
}