29requires std::invocable<const F&, std::ostream&>
class StreamFn {
35 std::invoke(s.f_, os);
54 auto format(
const auto& value,
auto& ctx)
const {
55 std::basic_stringstream<Char> ss;
57 return std::formatter<std::basic_string_view<Char>, Char>
::format(ss.view(), ctx);
69 constexpr Tab(std::string_view
tab = {
"\t"},
int indent = 0)
noexcept
75 static constexpr Tab spaces() noexcept {
return Tab(std::string_view(
" ")); }
80 constexpr int indent() const noexcept {
return indent_; }
81 constexpr std::string_view
tab() const noexcept {
return tab_; }
95 constexpr Tab&
operator--() noexcept { assert(indent_ > 0); --indent_;
return *
this; }
102 for (
int i = 0; i !=
tab.indent_; ++i)
108 std::string_view tab_;
112template<
class T,
class CharT =
char>
114 =
requires(std::basic_format_context<std::back_insert_iterator<std::basic_string<CharT>>, CharT>& ctx, T
const& v) {
115 std::formatter<std::remove_cvref_t<T>, CharT>{}.format(v, ctx);
120template<std::ranges::input_range R>
123 using View = std::views::all_t<R>;
129 const auto&
range()
const {
return range_; }
130 std::string_view
sep()
const {
return sep_; }
133 for (std::string_view
sep{};
const auto& elem : j.range_) {
142 std::string_view sep_;
155struct std::formatter<
fe::
Join<R>> {
156 using elem_t = std::remove_cvref_t<std::ranges::range_reference_t<std::views::all_t<R>>>;
157 std::formatter<elem_t> elem_fmt;
159 constexpr auto parse(std::format_parse_context& ctx) {
return elem_fmt.parse(ctx); }
161 auto format(
const fe::Join<R>& j,
auto& ctx)
const {
162 auto out = ctx.out();
163 for (std::string_view sep = {};
const auto& elem : j.
range()) {
164 out = std::ranges::copy(sep, out).out;
166 out = elem_fmt.format(elem, ctx);
189# define assertf(condition, ...) \
191 (void)sizeof(condition); \
194# define assertf(condition, ...) \
196 if (!(condition)) { \
197 std::println(std::cerr, "{}:{}: assertion `{}` failed", __FILE__, __LINE__, #condition); \
198 std::println(std::cerr, __VA_ARGS__); \
Join elements of range with sep.
const auto & range() const
std::string_view sep() const
friend std::ostream & operator<<(std::ostream &os, const Join &j)
Join(R &&range, std::string_view sep=", ")
std::views::all_t< R > View
Wrap a callable f(std::ostream&) -> std::ostream& so it streams via operator<< and std::format.
friend std::ostream & operator<<(std::ostream &os, StreamFn const &s)
constexpr Tab & operator+=(int indent) noexcept
constexpr std::string_view tab() const noexcept
constexpr Tab operator-(int indent) const noexcept
constexpr Tab & operator++() noexcept
friend std::ostream & operator<<(std::ostream &os, Tab tab)
constexpr Tab & operator-=(int indent) noexcept
constexpr int indent() const noexcept
constexpr Tab(const Tab &)=default
static constexpr Tab spaces() noexcept
constexpr Tab & operator--() noexcept
constexpr Tab operator+(int indent) const noexcept
constexpr Tab(std::string_view tab={"\t"}, int indent=0) noexcept
Span< const T, N > View
Read-only Span; use Span itself, if you want to write through its elements.
basic_ostream_formatter< char > ostream_formatter
Join(R &&, std::string_view=", ") -> Join< R >