From 9c56a8ce5c4f91686f80810c4559103bca00e34e Mon Sep 17 00:00:00 2001 From: Bjorn Fahller Date: Mon, 17 Jul 2017 12:35:39 +0200 Subject: [PATCH] Make format_arg() accept class hierarchies If a base class can be formatted, it is assumed that the hierarchy can be formatted from the base class. The idiom is not uncommon with ostreams. --- doc/api.rst | 30 ++++++++++++++++++++++++++++++ fmt/format.h | 6 +++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index 8dbef39e..8aacb6dc 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -84,6 +84,36 @@ Note in the example above the ``format_arg`` function ignores the contents of ``format_arg`` in :file:`fmt/time.h` for an advanced example of how to use the ``format_str`` argument to customize the formatted output. +This technique can also be used for formatting class hierarchies:: + + namespace local { + struct Parent { + Parent(int p) : p(p) {} + virtual void write(fmt::Writer &w) const { + w.write("Parent : p={}", p); + } + int p; + }; + + struct Child : Parent { + Child(int c, int p) : Parent(p), c(c) {} + virtual void write(fmt::Writer &w) const { + w.write("Child c={} : ", c); + Parent::write(w); + } + int c; + }; + + void format_arg(fmt::BasicFormatter &f, + const char *&format_str, const Parent &p) { + p.write(f.writer()); + } + } + Local::Child c(1,2); + Local::Parent &p = c; + fmt::print("via ref to base: {}\n", p); + fmt::print("direct to child: {}\n", c); + This section shows how to define a custom format function for a user-defined type. The next section describes how to get ``fmt`` to use a conventional stream output ``operator<<`` when one is defined for a user-defined type. diff --git a/fmt/format.h b/fmt/format.h index 719cc7c6..a4379da3 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -1255,9 +1255,9 @@ inline fmt::StringRef thousands_sep(...) { return ""; } typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED #endif -template -void format_arg(Formatter &, const Char *, const T &) { - FMT_STATIC_ASSERT(FalseType::value, +template +void format_arg(Formatter&, ...) { + FMT_STATIC_ASSERT(FalseType::value, "Cannot format argument. To enable the use of ostream " "operator<< include fmt/ostream.h. Otherwise provide " "an overload of format_arg.");