I want to write a function print(std::ranges::range auto&& range)
which prints a range to std::out
. This should be able to print a nested range recursively. I am new to this and still learning stuff. Here is a look at what I am expecting.
void print(ranges::range auto &&range)
{
if (std::is_convertible_v<ranges::range_value_t<decltype(range)>,ranges::range auto>)
// or if constexpr(...) or std::is_same_v ???
{
for (auto &&subrange : range)
{
std::cout << "{\n";
print(subrange);
std::cout << "}\n";
}
}
else
{
std::cout << "{";
for (auto &&i : range)
{
std::cout << i << ", ";
}
std::cout << "}\n";
}
}
Of course this doesn't work. I want to know how to do the comparison that some type can be a range? Any help is appreciated. Alternate approaches are welcome.
In gcc12 this results in
internal compiler error: Segmentation fault
[build] 90 | if (std::is_convertible_v<ranges::range_value_t<decltype(range)>,ranges::range auto>)
[build] | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] 0x7f11b04f8cef ???
[build] ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
[build] 0x7f11b04e050f __libc_start_call_main
[build] ../sysdeps/nptl/libc_start_call_main.h:58
[build] 0x7f11b04e05c8 __libc_start_main_impl
[build] ../csu/libc-start.c:381
You can determine whether it is a nested range by detecting whether the reference type (or value type) of the range also models the range
concept, for example
void print(ranges::range auto&& range)
{
// nested range
if constexpr (ranges::range<ranges::range_value_t<decltype(range)>>) {
// ...
}
else {
// ...
}
}
Note that if constexp
must be used to avoid hard errors for instantiation of branches that do not satisfy constraints. And it may also need to check whether the element type is printable through other concepts.