Skip to content
Snippets Groups Projects
Commit 233d58c8 authored by Sandipan Mohanty's avatar Sandipan Mohanty
Browse files

Provide range_output.hh

parent f91c0303
Branches main
No related tags found
No related merge requests found
#pragma once
#include <algorithm>
#include <iomanip>
#include <iosfwd>
#include <cxx20ranges>
#include <string>
namespace output {
template <class C>
concept RawArray = std::is_array_v<C>;
template <class C>
concept ArrayClass = requires(C c)
{
{ c[1ul] };
{ c.size() };
};
template <class C>
concept StringLike = std::convertible_to<C, std::string_view>;
namespace {
//auto size(const Container auto& C) { return C.size(); }
auto size(const RawArray auto& C) { return std::extent_v<std::remove_cvref_t<decltype(C)>>; }
}
template <class C>
concept ArrayLike = (not StringLike<C>)and(ArrayClass<C> or RawArray<C>);
template <class T>
void write_possibly_quoted(std::ostream& os, T&& t)
{
if constexpr (StringLike<T>) {
os << std::quoted(t);
} else {
os << t;
}
}
std::ostream& operator<<(std::ostream& os, const ArrayLike auto& c)
{
os << "[";
auto sz = size(c);
for (size_t i {}; i != sz; ++i) {
write_possibly_quoted(os, c[i]);
if (i + 1 < sz)
os << ", ";
}
return os << "]";
}
template <class T>
requires(not StringLike<T> and sr::range<T>)
std::ostream&
operator<<(std::ostream& os, T&& r)
{
os << "[";
for (auto el : r) {
write_possibly_quoted(os, el);
os << ", ";
}
return os << "]";
}
template <class SepType>
class rprinter {
std::ostream* strmptr = nullptr;
SepType sep;
public:
rprinter(SepType s)
: sep { s }
{
}
rprinter(const rprinter&) noexcept = default;
std::ostream& stream() { return *strmptr; }
void stream(std::ostream& os) { strmptr = &os; }
const auto& separator() const noexcept { return sep; }
};
template <>
class rprinter<void> {
std::ostream* strmptr = nullptr;
public:
std::ostream& stream() { return *strmptr; }
void stream(std::ostream& os) { strmptr = &os; }
};
template <class T>
rprinter<T> operator<<(std::ostream& os, rprinter<T> r)
{
r.stream(os);
return { r };
}
template <class T>
std::ostream& operator<<(rprinter<T> vp, sr::range auto&& t)
{
if constexpr (std::is_same_v<T, void>) {
for (auto&& el : t)
vp.stream() << el;
} else {
if (not sr::empty(t)) {
vp.stream() << *sr::begin(t);
sr::for_each(t | sv::drop(1), [&vp](auto&& el) {
vp.stream() << vp.separator() << el;
});
}
}
return vp.stream();
}
inline rprinter<void> unseparated;
inline rprinter<const char*> comma_separated { ", " };
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment