1. Problem It Solves
C++23 can flatten nested ranges with separators, generate repeated values lazily, and enumerate every combination across several ranges without constructing all results first. The goal is to make the relevant rule visible in code instead of relying on an assumption about what “C++23 support” means.
2. Prerequisites
Day 44: grouping and sampling views.
Tuples and nested ranges.
3. Core Idea
join_with stitches pieces with a delimiter, repeat is an on-demand source, and cartesian_product behaves like nested loops packaged as one lazy range. Read the syntax from left to right, identify the value, object, or range being transformed, and then check its resulting type, lifetime, or ownership. Standardization and implementation are separate: a C++23 mode may still lack one library component, so a feature-test macro is part of responsible portable use.
4. Minimal Syntax
auto pairs = std::views::cartesian_product(left, right);5. How It Works
The sample builds the smallest expression or object needed for Join-With, Repeat, and Cartesian-Product Views.
It joins words, repeats a fixed value, and produces all pairs when the adaptors exist. The compiler and library apply the relevant rule before the program observes the result.
The program prints or checks a delimited sequence, repeated values, and the full small product, making the important behavior easy to verify.
6. Common Mistakes
An unbounded repeat or a large Cartesian product can make iteration effectively infinite or explosively expensive; joined element and delimiter types must be compatible.
Enabling C++23 mode without checking the relevant feature macro may select code that the installed compiler or standard library does not implement yet.
7. When to Use It
Use it when the task involves small combinatorial searches, lazy constants, and readable joining of nested character ranges.
Avoid it when the task involves materializing a huge product or using lazy infinite sources without a terminating adaptor.
8. Simple Example
A test generator lazily combines two operation codes with three payload sizes to create six cases. The downloadable program keeps the data fixed so the output can be compared without entering input.
Complete sample code
Source file
cpp23/45_join_with_repeat_cartesian_product/main.cpp
#include <array>
#include <iostream>
#include <ranges>
#include <string_view>
#include <version>
int main() {
#if defined(__cpp_lib_ranges_join_with) && defined(__cpp_lib_ranges_repeat) && \
defined(__cpp_lib_ranges_cartesian_product)
std::array words{std::string_view{"C"}, std::string_view{"23"}};
for (char ch : std::views::join_with(words, std::string_view{"-"}))
std::cout << ch;
std::cout << '\n';
for (int value : std::views::repeat(7, 3))
std::cout << value << ' ';
std::cout << '\n';
std::array numbers{1, 2};
std::array letters{'a', 'b'};
for (auto [number, letter] :
std::views::cartesian_product(numbers, letters))
std::cout << number << letter << ' ';
std::cout << '\n';
#else
std::cout << "join_with, repeat, or cartesian_product unavailable\n";
#endif
}
9. Key Takeaways
Separate the language rule from compiler and library availability.
Keep lifetime, ownership, and deduced types visible when they affect correctness.
Prefer the smallest syntax that communicates the intent.
Guard facilities that are not yet uniformly implemented.
10. Self-Check Questions
Easy — What is the smallest syntax in Section 4, and what main job does it perform?
Medium — Read the sample program: which value, type, or branch is observed, and why?
Hard — If input sizes are
a,b, andc, what is the Cartesian-product size, and which empty-input case makes the whole product empty?