0% found this document useful (0 votes)
42 views6 pages

more cpp23 lib examples

Cpp23 lib examples

Uploaded by

mohamed.nar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
42 views6 pages

more cpp23 lib examples

Cpp23 lib examples

Uploaded by

mohamed.nar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

Seven More Examples for C++23 Library

Changes
C++23 gives us plenty of cool features. Below you can find more examples that extend my blog
article - C++23 Library Features and Reference Cards - C++ Stories.

1. std::ranges::to<>
The ranges::to<> feature allows you to easily convert ranges into containers:

#include <ranges>
#include <vector>
#include <iostream>
#include <string>
#include <unordered_map>
#include <map>

int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

std::unordered_map<int, std::string> number_to_text = {


{1, "one"}, {2, "two"}, {3, "three"}, {4, "four"}, {5, "five"},
{6, "six"}, {7, "seven"}, {8, "eight"}, {9, "nine"}, {10, "ten"}
};

auto even_numbers = numbers


| std::views::filter([](int n) { return n % 2 == 0; })
| std::ranges::to<std::vector>();

auto text_numbers_map = even_numbers


| std::views::transform([&number_to_text](int n) {
return std::pair{n, number_to_text.contains(n) ?
number_to_text[n] : "unknown" };
})
| std::ranges::to<std::map>();

std::cout << "Even numbers: ";


for (int n : even_numbers) std::cout << n << " ";
std::cout << "\nTextual numbers:\n";
for (const auto& [k, v] : text_numbers_map)
std::cout << k << " -> " << v << '\n';
}

Run @Compiler Explorer

As you can see, there's no issue in creating not only vectors but maps as well.
2. std::print and std::println
The new formatted output library simplifies printing. Here's an example that demonstrates
alignment, formatting, and table creation:

#include <print>
#include <unordered_map>
#include <string>
#include <numeric>

int main() {
// Store the data in an unordered_map (country -> size in km²)
std::unordered_map<std::string, double> country_sizes = {
{"USA", 9833517},
{"Canada", 9984670},
{"Australia", 7692024},
{"China", 9596961},
{"Poland", 312696}
};

constexpr double KM_TO_MI = 0.386102; // Conversion factor

const double total_km = std::accumulate(country_sizes.begin(),


country_sizes.end(), 0.0,
[](double sum, const auto& entry) { return
sum + entry.second; });
const double total_mi = total_km * KM_TO_MI;

// Table headers
std::println("{:<15} | {:>15} | {:>15}", "Country", "Size (km²)", "Size
(mi²)");
std::println("{:-<15}-+-{:-<15}-+-{:-<15}", "", "", ""); // Separator line

// Table rows
for (const auto& [country, size_km] : country_sizes) {
double size_mi = size_km * KM_TO_MI; // Compute size in square miles
dynamically
std::println("{:<15} | {:>15.0f} | {:>15.2f}", country, size_km,
size_mi);
}

// Footer
std::println("{:-<15}-+-{:-<15}-+-{:-<15}", "", "", ""); // Separator line
std::println("{:<15} | {:>15.0f} | {:>15.2f}", "Total", total_km, total_mi);
}

Run @Compiler Explorer

Example output:
Country | Size (km²) | Size (mi²)
----------------+-----------------+----------------
Poland | 312696 | 120732.55
China | 9596961 | 3705405.84
Australia | 7692024 | 2969905.85
Canada | 9984670 | 3855101.06
USA | 9833517 | 3796740.58
----------------+-----------------+----------------
Total | 37419868 | 14447885.87

3. std::optional Monadic Operations


The new and_then , transform , and or_else functions make working with std::optional
more expressive. Here's an example that chains operations to process user input.

#include <optional>
#include <iostream>
#include <string>
#include <algorithm>

std::optional<std::string> get_user_input() {
std::string input;
std::cout << "Enter your name: ";
std::getline(std::cin, input);
if (input.empty()) return std::nullopt;
return input;
}

int main() {
auto result = get_user_input()
.transform([](std::string name) {
std::transform(name.begin(), name.end(), name.begin(), ::toupper);
return name;
})
.and_then([](std::string name) {
if (name == "ADMIN") return std::optional<std::string>("Welcome,
Admin!");
return std::optional<std::string>("Hello, " + name + "!");
})
.or_else([] {
return std::optional<std::string>("No input provided.");
});

std::cout << *result << "\n";


}

Experiment at @Compiler Explorer


4. std::generator
The std::generator feature simplifies creating lazy sequences. Here's an example of reading line
by line from a file:

#include <generator>
#include <fstream>
#include <iostream>
#include <string>

// Coroutine to read lines from a file


std::generator<std::string> read_lines(const std::string& filename) {
std::ifstream file(filename);
std::string line;
while (std::getline(file, line)) {
co_yield line;
}
}

int main() {
const std::string temp_filename = "temp_file.txt";
{
std::ofstream temp_file(temp_filename);
temp_file << "Line 1: Hello, World!\n";
temp_file << "Line 2: This is a test.\n";
temp_file << "Line 3: C++ coroutines are cool!\n";
}

for (const auto& line : read_lines(temp_filename)) {


std::cout << line << std::endl;
}
}

See @Compiler Explorer

5. std::mdspan
The std::mdspan feature is useful for multidimensional data. Here's an example of matrix
multiplication.

#include <https://raw.githubusercontent.com/kokkos/mdspan/single-
header/mdspan.hpp>
#include <vector>
#include <print>

void multiply_matrices(std::mdspan<int, std::dextents<size_t, 2>> A,


std::mdspan<int, std::dextents<size_t, 2>> B,
std::mdspan<int, std::dextents<size_t, 2>> C) {
for (size_t i = 0; i < A.extent(0); ++i) {
for (size_t j = 0; j < B.extent(1); ++j) {
C[i, j] = 0;
std::print("{}{}: ", i, j);
for (size_t k = 0; k < A.extent(1); ++k) {
std::print("+= {} x {}, ", A[i, k], B[k, j]);
C[i, j] += A[i, k] * B[k, j];
}
std::println();
}
}
}

int main() {
std::vector<int> A_data = {1, 2, 3, 4, 5, 6};
std::vector<int> B_data = {1, 2, 3, 4, 5, 6};
std::vector<int> C_data(4);

auto A = std::mdspan(A_data.data(), 2, 3);


auto B = std::mdspan(B_data.data(), 3, 2);
auto C = std::mdspan(C_data.data(), 2, 2);

multiply_matrices(A, B, C);

for (size_t i = 0; i < C.extent(0); ++i) {


for (size_t j = 0; j < C.extent(1); ++j) {
std::print("{} ", C[i, j]);
}
std::println();
}
}

Experiment @Compiler Explorer

6. cartesian_product , enumerate , and zip


#include <ranges>
#include <print>
#include <vector>

int main() {
std::vector<int> range1 = {1, 2, 3};
std::vector<char> range2 = {'A', 'B', 'C'};

auto product = std::views::cartesian_product(range1, range2);


std::println("Cartesian Product:");
for (const auto& [a, b] : product)
std::println("({}, {})", a, b);

auto enumerated = std::views::enumerate(range1);


std::println("\nEnumerated Range:");
for (const auto& [index, value] : enumerated)
std::println("Index: {}, Value: {}", index, value);

auto zipped = std::views::zip(range1, range2);


std::println("\nZipped Ranges:");
for (const auto& [a, b] : zipped)
std::println("({}, {})", a, b);
}
Run @Compiler Explorer

7. chunk , slide and stride


#include <ranges>
#include <print>
#include <vector>

int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};

// Chunk: divide the range into groups of 3


auto chunks = std::views::chunk(numbers, 3);
std::println("Chunks of 3:");
for (const auto& chunk : chunks) {
for (int n : chunk)
std::print("{} ", n);
std::println("");
}

// Slide: create overlapping subranges of size 3


auto sliding = std::views::slide(numbers, 3);
std::println("\nSliding Window of 3:");
for (const auto& window : sliding) {
for (int n : window)
std::print("{} ", n);
std::println("");
}

// Stride: skip every 2 elements


auto strided = std::views::stride(numbers, 2);
std::println("\nStrided Range (step 2):");
for (int n : strided)
std::print("{} ", n);
}

Run @Compiler Explorer

You might also like