Difference between std::ranges::subrange
and std::span
What is the difference between std::ranges::subrange
and std::span
?
std::ranges::subrange
and std::span
both provide views over a sequence of elements without owning the elements themselves, but they serve different purposes and have distinct characteristics.
std::ranges::subrange
has the following characteristics:
- Part of Ranges Library:
std::ranges::subrange
is part of the Ranges library, introduced in C++20. It provides a way to create views of a range defined by iterators. - Flexible Iterators: It can work with any type of iterator, not just pointers. This means you can create a subrange from various types of containers and iterators.
- Slicing: You can create a subrange from a subset of a container, not necessarily starting from the beginning.
- Non-Contiguous: Subranges do not require the underlying data to be contiguous in memory.
The following program uses std::ranges::subrange
to view part of an underlying std::vector
:
#include <iostream>
#include <ranges>
#include <vector>
int main() {
std::vector<int> Nums{1, 2, 3, 4, 5};
std::ranges::subrange View{
Nums.begin() + 1, Nums.end() - 1};
for (int n : View) {
std::cout << n << ", ";
}
}
2, 3, 4,
std::span
has these characteristics:
- Part of Utilities Library:
std::span
is part of the Utilities library and was introduced in C++20. It provides a view over a contiguous sequence of elements, typically from an array or astd::vector
. - Pointer-Based: It is essentially a pair of a pointer and a size, meaning it only works with contiguous memory blocks.
- Fixed Size:
std::span
views are fixed at the time of creation and cannot be resized. - More Limited Use: It is more limited in scope compared to
std::ranges::subrange
, focusing on contiguous memory.
The following example program uses std::span
to create a view of an underlying std::vector
:
#include <vector>
#include <span>
#include <iostream>
int main() {
std::vector<int> Nums{1, 2, 3, 4, 5};
std::span<int> View{Nums.data(), Nums.size()};
for (int n : View) {
std::cout << n << ", ";
}
}
1, 2, 3, 4, 5,
Key Differences
- Flexibility:
std::ranges::subrange
is more flexible, working with various iterators and non-contiguous memory, whilestd::span
is limited to contiguous memory. - Purpose:
std::ranges::subrange
is useful for range-based operations and slicing, whereasstd::span
is more suited for working with contiguous arrays and interfacing with legacy APIs. - Usage Context: Use
std::ranges::subrange
for general range operations andstd::span
when you need a simple, contiguous view of data.
By understanding these differences, you can choose the appropriate type for your specific needs in C++.
Creating Views using std::ranges::subrange
This lesson introduces std::ranges::subrange, allowing us to create non-owning ranges that view some underlying container