kennen:include:ranges
<ranges>
Bereiche (ab C++20) sind Elementfolgen, auf die begin(r)
und end(r)
anwendbar sind.
Im Namensraum std::ranges::views
oder kurz std::views
definierte Sichten auf Bereiche lassen sich über Pipes |
aneinander koppeln.
Sie liefern die Werte eines Bereiches einzeln auf Anforderung.
- views_pipelines.cpp
#include <iostream> #include <ranges> int main() { using namespace std::views; auto output = iota(1) | filter([](int x){ return x%2 == 0; }) | transform([](int x){ return 3*x; }) | take(10); // no calculation is done up to here (lazy evaluation) for (auto e : output) std::cout << e << ' '; }
Anfang und Ende eines Views müssen nicht denselben Typ besitzen. Werden Iteratoren des selben Typs benötigt, können diese mit std::views::common
erzeugt werden:
- views_common.cpp
#include <iostream> #include <ranges> #include <vector> int main() { using namespace std::views; auto numbers = iota(1, 10) | common; auto v = std::vector<int>{numbers.begin(), numbers.end()}; for (auto e : v) std::cout << e << ' '; }
Fabriken
erzeugen Bereiche.
empty | leerer Bereich |
single(value) | Bereich mit nur einem Wert |
iota(start) | (unendlicher) Bereich mit Werten beginnend bei start , zählt mit ++ hoch |
iota(start, end) | Zählbereich mit Werten, endet vor end |
ranges::istream_view<T>(istream) | liest Werte vom Typ T aus dem Eingabestrom istream |
- istream_view.cpp
#include <iostream> #include <ranges> #include <string> #include <sstream> int main() { auto input = std::istringstream{"0 1 2 3 4 5 6 7 8 9"}; auto below_5 = std::ranges::istream_view<int>(input) | std::views::take_while([](auto x) { return x < 5; }); for (auto e : below_5) std::cout << e << ' '; }
Sichten
übernehmen einen Bereich, verarbeiten dessen Elemente e
und geben sie weiter.
all | gibt alle Elemente weiter |
common | erzeugt Bereich, bei dem begin(r) und end(r) den selben Typ haben |
counted(iter, n) | liefert n Werte, beginnend mit Iterator iter |
drop(n) | überspringt die ersten n Elemente |
drop_while(pred) | überspringt Elemente, solange pred(e) erfüllt ist |
filter(pred) | gibt nur die Elemente weiter, für die pred(e) erfüllt ist |
reverse | kehrt Reihenfolge der Elemente um |
take(n) | gibt nur die ersten n Elemente weiter |
take_while(pred) | gibt Elemente nur solange weiter, wie pred(e) erfüllt ist |
transform(f) | wendet f auf jedes Element e an, gibt f(e) weiter |
join | wandelt einen Bereich von Bereichen in einen "flachen" Bereich um |
split(delim) | erzeugt einen Bereich von Teilbereichen, delim kann einzelnes Element oder eine Folge sein |
elements<N> | gibt den N -ten Bestandteil von tupelartigen Elementen weiter |
keys | gibt alle Schlüssel von Schlüssel-Wert-Paaren weiter (elements<0> ) |
values | gibt alle Werte von Schlüssel-Wert-Paaren weiter (elements<1> ) |
Beispiele
- views_examples.cpp
#include <ranges> #include <iostream> #include <map> #include <string> #include <vector> template <typename Range, typename Msg> void show(Range&& r, Msg message) { std::cout.width(30); std::cout << std::left << message << " : ["; int cnt = 0; for (auto&& e : r) { std::cout << (cnt++ ? ",":""); std::cout << e; } std::cout << "]\n"; } template <typename Range, typename Msg> void show_range_of_ranges(Range&& r, Msg message) { std::cout.width(30); std::cout << std::left << message << " : ["; int cnt = 0; for (auto&& inner_range : r) { std::cout << (cnt++ ? ",":"") << "["; int inner_cnt = 0; for (auto&& e : inner_range) { std::cout << (inner_cnt++ ? ",":""); std::cout << e; } std::cout << "]"; } std::cout << "]\n"; } int main() { using namespace std::views; auto v = std::vector{0,1,2,3,4,5}; auto s = std::string{"AB CD E"}; auto m = std::map<std::string,int>{{"wrong", 6*9}, {"answer", 42}}; show( empty<int>, "empty<T>"); show( single(42), "single(42)"); show( iota(0,6), "iota(0,6)"); show( iota(0) | take(3), "iota(0) | take(3)"); show( counted(begin(v), 3), "counted(begin(v),3)"); show( v | all, "v | all"); show( v | reverse, "v | reverse"); show( v | take_while([](int x){ return x < 3; }), "v | take_while(below_3)"); show( v | drop_while([](int x){ return x < 3; }), "v | drop_while(below_3)"); show( v | filter([](int x){ return x%2 != 0; }), "v | filter(odd)"); show( v | transform([](int x){ return x*x; }), "v | transform(square)"); show( s , "s"); show_range_of_ranges( s | split(' '), "s | split(\' \')"); show( s | split(' ') | join, "s | split(\' \') | join"); show( m | keys , "m | keys"); show( m | values , "m | values"); }
erzeugt die Ausgabe
empty<T> : [] single(42) : [42] iota(0,6) : [0,1,2,3,4,5] iota(0) | take(3) : [0,1,2] counted(begin(v),3) : [0,1,2] v | all : [0,1,2,3,4,5] v | reverse : [5,4,3,2,1,0] v | take_while(below_3) : [0,1,2] v | drop_while(below_3) : [3,4,5] v | filter(odd) : [1,3,5] v | transform(square) : [0,1,4,9,16,25] s : [A,B, ,C,D, ,E] s | split(' ') : [[A,B],[C,D],[E]] s | split(' ') | join : [A,B,C,D,E] m | keys : [answer,wrong] m | values : [42,54]
kennen/include/ranges.txt · Zuletzt geändert: 2020-07-08 18:10 von 127.0.0.1