Expert · Modern C++: lambdas, C++17 and C++20 essentials · topic 33 of 42 · 30 min
C++20 ranges, views and other C++20 essentials
Explanation
Why ranges?
Classic STL algorithms take two iterators: std::sort(v.begin(), v.end()). Passing the wrong pair (v.begin(), w.end()) compiles and corrupts memory. A range is anything with a begin and an end, like a container. The C++20 ranges library (<ranges> and the std::ranges:: algorithms) lets you pass the range itself.
#include <algorithm>
#include <ranges>
#include <vector>
std::vector<int> v = {5, 2, 8, 1};
std::ranges::sort(v); // 1 2 5 8
auto it = std::ranges::find(v, 8);
bool allPositive = std::ranges::all_of(v, [](int x) { return x > 0; });Projections
struct Order { std::string id; int amount; };
std::vector<Order> orders = {{"A1", 499}, {"A2", 120}, {"A3", 999}};
std::ranges::sort(orders, {}, &Order::amount); // sort by amount
auto big = std::ranges::max_element(orders, {}, &Order::amount); // order with the largest amountViews: lazy pipelines
#include <iostream>
#include <ranges>
#include <vector>
int main() {
std::vector<int> marks = {35, 82, 47, 91, 28, 66};
auto passedDoubled = marks
| std::views::filter([](int m) { return m >= 40; })
| std::views::transform([](int m) { return m * 2; });
for (int x : passedDoubled) std::cout << x << ' '; // 164 94 182 132
std::cout << '\n';
for (int i : std::views::iota(1, 6)) std::cout << i; // 12345
std::cout << '\n';
for (int x : marks | std::views::reverse | std::views::take(2)) std::cout << x << ' '; // 66 28
}Other C++20 features worth knowing
| Feature | What it gives you |
|---|---|
| Concepts | Named requirements on templates and clearer errors (seen in the templates topic) |
| std::span<T> | A non-owning view of a contiguous array: pass vectors, arrays and C arrays to one function |
| Designated initialisers | Point p{.x = 1, .y = 2}; names the fields when initialising a struct |
| Three-way comparison <=> | One defaulted operator gives all comparisons |
| std::format | Python-style formatting: std::format("{:.2f}", x) |
| contains() | map.contains(key) and set.contains(key) |
| std::jthread | A thread that joins itself in its destructor (RAII) |
| Modules | import instead of #include for faster builds; build tool support is still maturing |
| Coroutines | co_await / co_yield for async code and generators; mostly used through libraries |
#include <span>
double average(std::span<const int> values) { // works with vector, array, C array
if (values.empty()) return 0;
long long sum = 0;
for (int v : values) sum += v;
return static_cast<double>(sum) / values.size();
}
std::vector<int> a = {70, 80};
int b[] = {60, 90, 75};
average(a);
average(b);Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
C++20 ranges, views and other C++20 essentials · 1/6
C plus plus twenty modernised the algorithms with ranges.
Prefer a video by a teacher? Find free videos on “c++20 ranges views filter transform pipe tutorial” on YouTube ↗
In real life: Today's high-value UPI payments
A shop owner wants the IDs of today's UPI payments above Rs 1,000, newest first, for a quick check. A ranges pipeline (filter, then transform to the ID) reads like the requirement and makes no intermediate copies.
#include <iostream>
#include <ranges>
#include <string>
#include <vector>
struct Payment { std::string id; int rupees; };
int main() {
std::vector<Payment> today = {{"U101", 250}, {"U102", 1800}, {"U103", 999}, {"U104", 5200}};
auto bigIds = today
| std::views::reverse
| std::views::filter([](const Payment& p) { return p.rupees > 1000; })
| std::views::transform(&Payment::id);
for (const auto& id : bigIds) std::cout << id << ' '; // U104 U102
std::cout << '\n';
}Practice (0/4 done)
Which is the C++20 ranges way to sort vector v?
What does this print? std::vector<int> v = {1, 2, 3, 4, 5, 6}; for (int x : v | std::views::filter([](int n) { return n % 2 == 0; }) | std::views::transform([](int n) { return n * n; })) std::cout << x << " ";
When does a view like std::views::filter do its work?
Given std::vector<Student> (name, marks), use C++20 ranges to: sort by marks descending with a projection, then print the names of the first 3 students who scored at least 60 using views::filter, views::transform and views::take.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- auto, structured bindings and other C++17 conveniencesModern C++: lambdas, C++17 and C++20 essentials · same module
- Lambdas: small functions written in placeModern C++: lambdas, C++17 and C++20 essentials · same module
- Arrays, std::array and a first look at std::vectorReferences, pointers, arrays and strings
- Operator overloadingOperator overloading, inheritance and polymorphism
- Reading input and formatting outputFirst steps: compiling, output, variables and input
- Your first program: main, cout and namespacesFirst steps: compiling, output, variables and input
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What does the | operator do between views?
Answer: Chains view steps into a pipeline
Range adaptors compose with the pipe operator.
What is std::span<const int> good for?
Answer: Passing any contiguous array (vector, std::array, C array) to a function without copying
span is a non-owning view of contiguous elements.
Which is a valid C++20 designated initialiser for struct P { int x; int y; };?
Answer: P p{.x = 1, .y = 2};
Designators use .name and must follow the declaration order.
What is the main risk of returning a view of a local vector?
Answer: The view dangles because the vector is destroyed
Views reference their source; the source must outlive them.
Which C++ standard introduced optional, variant and string_view?Related
Why can you not call std::sort on a std::list?Related
Answer: std::sort needs random-access iterators; list iterators are only bidirectional
Use the member function list.sort() instead.
What does a C++20 concept do?Related
Answer: States compile-time requirements on template arguments, giving clearer errors
Concepts constrain templates and improve error messages.
What is the main advantage of std::vector over a C-style array?Related
Answer: Its size can change at run time and it knows its size
vector grows with push_back and reports size(); it also manages its own memory.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Modern C++: lambdas, C++17 and C++20 essentials”. The module exam comes next.
- Module 8 exam: Modern C++ · 12 questions · 25 min, without help. 4 topics of this module still to finish first.
- Then the next module, Exceptions, concurrency and building projects with CMake. 42 topics left in the course before the final exam.
← Previous: std::optional, std::variant and std::string_view