std::span¶
#include <iostream>
#include <vector>
#include <span> // C++20 header
#include <array>// Function that takes a std::span of integers
void process_data(std::span<const int> data_view) {
std::cout << "Processing data: ";
for (int value : data_view) {
std::cout << value << " ";
}
std::cout << std::endl;
}// 1. Using a C-style array
int c_array[] = {10, 20, 30, 40, 50};
std::span<const int> span_from_c_array(c_array);
process_data(span_from_c_array);
// 2. Using a std::vector
std::vector<int> my_vector = {1, 2, 3, 4, 5, 6, 7};
std::span<const int> span_from_vector(my_vector);
process_data(span_from_vector);
// 3. Using a std::array
std::array<int, 4> my_array = {100, 200, 300, 400};
std::span<const int> span_from_std_array(my_array);
process_data(span_from_std_array);
// 4. Creating a sub-span (a view of a portion of the original data)
// View from index 2, for 3 elements
std::span<const int> sub_span = span_from_vector.subspan(2, 3);
process_data(sub_span);
// 5. Modifying data through a non-const span (if allowed by original data)
std::vector<int> mutable_vector = {10, 20, 30};
std::span<int> mutable_span(mutable_vector);
mutable_span[0] = 5; // Modifies mutable_vector[0]
std::cout << "Modified vector through span: " << mutable_vector[0] << std::endl;
process_data(mutable_vector);Processing data: 10 20 30 40 50
Processing data: 1 2 3 4 5 6 7
Processing data: 100 200 300 400
Processing data: 3 4 5
Modified vector through span: 5
Processing data: 5 20 30
Ranges¶
#include <ranges>auto const ints = {0, 1, 2, 3, 4, 5};
auto even = [](int i) { return 0 == i % 2; };
auto square = [](int i) { return i * i; };
// the "pipe" syntax of composing the views:
for (int i : ints | std::views::filter(even) | std::views::transform(square))
std::cout << i << ' ';
std::cout << '\n';
// a traditional "functional" composing syntax:
for (int i : std::views::transform(std::views::filter(ints, even), square))
std::cout << i << ' ';0 4 16
0 4 16 Three-way-compare¶
#include <compare> // Required for std::strong_orderingstruct Point {
int x;
int y;
// Explicitly defining the three-way comparison operator
auto operator<=>(const Point& other) const {
if (auto cmp = x <=> other.x; cmp != 0) {
return cmp; // If x's are different, return their comparison result
}
return y <=> other.y; // Otherwise, compare y's
}
// operator== is still needed for types where operator<=> might not yield a strong ordering (e.g., floating-point types)
// or if you want a custom equality comparison that differs from the three-way comparison.
// However, for types like this Point struct, if operator<=> returns std::strong_ordering,
// the compiler can synthesize operator== from it.
// For demonstration, we'll explicitly define it here.
bool operator==(const Point& other) const {
return x == other.x && y == other.y;
}
};Point p1{1, 2};
Point p2{3, 4};
Point p3{1, 2};
std::cout << std::boolalpha; // Output booleans as true/false
// Using the synthesized comparison operators
std::cout << "p1 < p2: " << (p1 < p2) << std::endl;
std::cout << "p1 == p3: " << (p1 == p3) << std::endl;
std::cout << "p2 > p1: " << (p2 > p1) << std::endl;
std::cout << "p1 != p2: " << (p1 != p2) << std::endl;p1 < p2: true
p1 == p3: true
p2 > p1: true
p1 != p2: true