From 233d58c81a3b5bc9b6d01d4555302d588d9f3e59 Mon Sep 17 00:00:00 2001 From: Sandipan Mohanty <s.mohanty@fz-juelich.de> Date: Fri, 13 May 2022 12:00:33 +0200 Subject: [PATCH] Provide range_output.hh --- code/include/range_output.hh | 113 +++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 code/include/range_output.hh diff --git a/code/include/range_output.hh b/code/include/range_output.hh new file mode 100644 index 0000000..65508ea --- /dev/null +++ b/code/include/range_output.hh @@ -0,0 +1,113 @@ +#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 { ", " }; + +} -- GitLab