C++ Ranges Introduction
A range is a group of values with a beginning and an end. The ranges library adds algorithms that take a whole range in one argument.
Sorting the long way and the short way
The first sort call passes a beginning and an end. The second call passes the whole vector and prints the same row.
#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
int main() {
std::vector<int> first = {9, 3, 8, 5};
std::sort(first.begin(), first.end());
std::cout << "Old:";
for (int n : first) {
std::cout << " " << n;
}
std::cout << std::endl;
std::vector<int> second = {9, 3, 8, 5};
std::ranges::sort(second);
std::cout << "Ranges:";
for (int n : second) {
std::cout << " " << n;
}
std::cout << std::endl;
return 0;
}Finding a value
std::ranges::find returns where the value sits. The search counts as found when that position is not end().
#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
int main() {
std::vector<int> scores = {42, 17, 88, 59};
std::cout << std::boolalpha;
std::cout << "88 found: " << (std::ranges::find(scores, 88) != scores.end()) << std::endl;
std::cout << "100 found: " << (std::ranges::find(scores, 100) != scores.end()) << std::endl;
return 0;
}Sorting by one member
A projection picks the value an algorithm compares instead of the whole object. Here the projection is &Item::price, so the sort compares prices.
#include <algorithm>
#include <iostream>
#include <ranges>
#include <string>
#include <vector>
struct Item {
std::string name;
int price;
};
int main() {
std::vector<Item> items = {{"Notebook", 450}, {"Pen", 120}, {"Mug", 300}};
std::ranges::sort(items, {}, &Item::price);
for (Item item : items) {
std::cout << item.name << " " << item.price << std::endl;
}
return 0;
}Counting the matches
std::ranges::count_if runs a test on each value. It returns how many values pass the test.
#include <algorithm>
#include <iostream>
#include <ranges>
#include <vector>
int main() {
std::vector<int> scores = {42, 17, 88, 59, 73};
auto passing = std::ranges::count_if(scores, [](int score) {
return score >= 50;
});
std::cout << "Passing: " << passing << std::endl;
return 0;
}Example
#include <algorithm>
#include <iostream>
#include <ranges>
#include <string>
#include <vector>
struct Item {
std::string name;
int price;
};
int main() {
std::vector<Item> items = {{"Pen", 120}, {"Notebook", 450}, {"Mug", 300}, {"Ruler", 200}};
std::ranges::sort(items, {}, &Item::name);
std::cout << "By name:";
for (Item item : items) {
std::cout << " " << item.name;
}
std::cout << std::endl;
std::ranges::sort(items, {}, &Item::price);
std::cout << "By price:";
for (Item item : items) {
std::cout << " " << item.name;
}
std::cout << std::endl;
return 0;
}Key points
- Use std::ranges::sort to sort a whole container with one argument.
- std::ranges::find returns a position that is checked against end().
- A projection picks the value an algorithm compares instead of the whole object.
- std::ranges::count_if counts the values that pass a test.
In this example, the first sort uses a projection on the name member, so the items line up in name order. The second sort uses a projection on the price member. The same vector then lines up from the cheapest item to the dearest one.
Note
The ranges forms take the whole range, where the older forms take a beginning and an end as two arguments.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does std::ranges::find return when no value matches?