From 95a53e1f62d874aaa987b3f0750361d3393874b8 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sat, 19 Nov 2016 07:39:07 -0800 Subject: [PATCH] Refactor argument visitor API (#422) --- fmt/format.h | 41 ++++++++++++++++++++++++++++++----------- fmt/printf.h | 16 +++++++++------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/fmt/format.h b/fmt/format.h index 848d79a4..0eb1f457 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -1536,7 +1536,8 @@ typedef basic_format_args> wformat_args; #define FMT_DISPATCH(call) static_cast(this)->call template -typename std::result_of::type visit(Visitor &&vis, format_arg arg) { +typename std::result_of::type visit(Visitor &&vis, + format_arg arg) { switch (arg.type) { case format_arg::NONE: case format_arg::NAMED_ARG: @@ -1746,7 +1747,9 @@ class ArgVisitor { called. \endrst */ - Result visit(const format_arg &arg) { return fmt::visit(*this, arg); } + Result visit(const format_arg &arg) { + return fmt::visit(*static_cast(this), arg); + } }; enum Alignment { @@ -2056,6 +2059,22 @@ class ArgFormatterBase : public ArgVisitor { writer_.write_int(reinterpret_cast(p), spec_); } + template + void write_str(Arg::StringValue value, + typename EnableIf< + std::is_same::value && + std::is_same::value, int>::type = 0) { + writer_.write_str(value, spec_); + } + + template + void write_str(Arg::StringValue value, + typename EnableIf< + !std::is_same::value || + !std::is_same::value, int>::type = 0) { + // Do nothing. + } + protected: BasicWriter &writer() { return writer_; } FormatSpec &spec() { return spec_; } @@ -2083,13 +2102,15 @@ class ArgFormatterBase : public ArgVisitor { template void visit_any_double(T value) { writer_.write_double(value, spec_); } - void visit_bool(bool value) { + using ArgVisitor::operator(); + + void operator()(bool value) { if (spec_.type_) return visit_any_int(value); write(value); } - void visit_char(int value) { + void operator()(wchar_t value) { if (spec_.type_ && spec_.type_ != 'c') { spec_.flags_ |= CHAR_FLAG; writer_.write_int(value, spec_); @@ -2119,23 +2140,21 @@ class ArgFormatterBase : public ArgVisitor { *out = internal::CharTraits::cast(value); } - void visit_cstring(const char *value) { + void operator()(const char *value) { if (spec_.type_ == 'p') return write_pointer(value); write(value); } - void visit_string(Arg::StringValue value) { + void operator()(Arg::StringValue value) { writer_.write_str(value, spec_); } - using ArgVisitor::visit_wstring; - - void visit_wstring(Arg::StringValue value) { - writer_.write_str(value, spec_); + void operator()(Arg::StringValue value) { + write_str(value); } - void visit_pointer(const void *value) { + void operator()(const void *value) { if (spec_.type_ && spec_.type_ != 'p') report_unknown_type(spec_.type_, "pointer"); write_pointer(value); diff --git a/fmt/printf.h b/fmt/printf.h index 85572c4e..8f9278fe 100644 --- a/fmt/printf.h +++ b/fmt/printf.h @@ -210,8 +210,10 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase { BasicPrintfArgFormatter(BasicWriter &writer, FormatSpec &spec) : internal::ArgFormatterBase(writer, spec) {} + using Base::operator(); + /** Formats an argument of type ``bool``. */ - void visit_bool(bool value) { + void operator()(bool value) { FormatSpec &fmt_spec = this->spec(); if (fmt_spec.type_ != 's') return this->visit_any_int(value); @@ -220,7 +222,7 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase { } /** Formats a character. */ - void visit_char(int value) { + void operator()(wchar_t value) { const FormatSpec &fmt_spec = this->spec(); BasicWriter &w = this->writer(); if (fmt_spec.type_ && fmt_spec.type_ != 'c') @@ -243,9 +245,9 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase { } /** Formats a null-terminated C string. */ - void visit_cstring(const char *value) { + void operator()(const char *value) { if (value) - Base::visit_cstring(value); + Base::operator()(value); else if (this->spec().type_ == 'p') write_null_pointer(); else @@ -253,15 +255,15 @@ class BasicPrintfArgFormatter : public internal::ArgFormatterBase { } /** Formats a pointer. */ - void visit_pointer(const void *value) { + void operator()(const void *value) { if (value) - return Base::visit_pointer(value); + return Base::operator()(value); this->spec().type_ = 0; write_null_pointer(); } /** Formats an argument of a custom (user-defined) type. */ - void visit_custom(internal::Arg::CustomValue c) { + void operator()(internal::Arg::CustomValue c) { const Char format_str[] = {'}', '\0'}; auto args = basic_format_args>(); basic_format_context ctx(format_str, args);