diff --git a/examples/format.cc b/examples/format.cc index cd818a9..da859be 100644 --- a/examples/format.cc +++ b/examples/format.cc @@ -12,29 +12,17 @@ using namespace ostd::string_literals; struct Foo { }; -/* implementing formatting for custom objects - external function */ -template -void to_format(Foo const &, R &writer, format_spec const &fs) { - switch (fs.spec()) { - case 'i': - range_put_all(writer, "Foo1"_sr); - break; - default: - range_put_all(writer, "Foo2"_sr); - break; - } -} - -struct Bar { - /* implementing formatting for custom objects - method */ +/* implementing formatting for custom objects */ +template<> +struct format_traits { template - void to_format(R &writer, format_spec const &fs) const { + static void to_format(Foo const &, R &writer, format_spec const &fs) { switch (fs.spec()) { case 'i': - range_put_all(writer, "Bar1"_sr); + range_put_all(writer, "Foo1"_sr); break; default: - range_put_all(writer, "Bar2"_sr); + range_put_all(writer, "Foo2"_sr); break; } } @@ -116,10 +104,6 @@ int main() { writefln("%s", Foo{}); writefln("%i", Foo{}); - /* again, but using a method for formatting */ - writefln("%s", Bar{}); - writefln("%i", Bar{}); - /* formatting into a string sink (can be any output range, but * appender makes sure the capacity is unlimited so it's safe) */ diff --git a/ostd/format.hh b/ostd/format.hh index 0dec6ee..994495d 100644 --- a/ostd/format.hh +++ b/ostd/format.hh @@ -36,16 +36,9 @@ struct format_error: std::runtime_error { struct format_spec; -template< - typename T, typename R, typename = std::enable_if_t().to_format( - std::declval(), std::declval() - )), void - >> -> -inline void to_format(T const &v, R &writer, format_spec const &fs) { - v.to_format(writer, fs); -} +/* empty by default, SFINAE friendly */ +template +struct format_traits {}; /* implementation helpers */ namespace detail { @@ -174,9 +167,9 @@ namespace detail { template constexpr bool is_tuple_like = decltype(tuple_like_test(0))::value; - /* test whether to_format works */ + /* test if format traits are available for the type */ template - static std::true_type test_tofmt(decltype(to_format( + static std::true_type test_tofmt(decltype(format_traits::to_format( std::declval(), std::declval(), std::declval() )) *); @@ -660,7 +653,7 @@ private: void write_val(R &writer, bool escape, T const &val) const { /* stuff fhat can be custom-formatted goes first */ if constexpr(detail::fmt_tofmt_test>) { - to_format(val, writer, *this); + format_traits::to_format(val, writer, *this); return; } /* second best, we can convert to string slice */