From d4084ac5b135b86ee6afb3b614039b9d39989842 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 20 Nov 2016 08:47:24 -0800 Subject: [PATCH] Get rid of ArgVisitor --- fmt/format.h | 201 ++-------------------------------- test/custom-formatter-test.cc | 6 +- test/format-test.cc | 11 +- test/util-test.cc | 75 +++---------- 4 files changed, 36 insertions(+), 257 deletions(-) diff --git a/fmt/format.h b/fmt/format.h index 4ce0c1b1..dd3ac296 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -1580,173 +1580,6 @@ typename std::result_of::type visit(Visitor &&vis, return typename std::result_of::type(); } -/** - \rst - An argument visitor based on the `curiously recurring template pattern - `_. - - To use `~fmt::ArgVisitor` define a subclass that implements some or all of the - visit methods with the same signatures as the methods in `~fmt::ArgVisitor`, - for example, `~fmt::ArgVisitor::visit_int()`. - Pass the subclass as the *Impl* template parameter. Then calling - `~fmt::ArgVisitor::visit` for some argument will dispatch to a visit method - specific to the argument type. For example, if the argument type is - ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass - will be called. If the subclass doesn't contain a method with this signature, - then a corresponding method of `~fmt::ArgVisitor` will be called. - - **Example**:: - - class MyArgVisitor : public fmt::ArgVisitor { - public: - void visit_int(int value) { fmt::print("{}", value); } - void visit_double(double value) { fmt::print("{}", value ); } - }; - \endrst - */ -template -class ArgVisitor { - private: - typedef internal::Arg Arg; - - public: - void report_unhandled_arg() {} - - Result visit_unhandled_arg() { - FMT_DISPATCH(report_unhandled_arg()); - return Result(); - } - - /** Visits an ``int`` argument. **/ - Result visit_int(int value) { - return FMT_DISPATCH(visit_any_int(value)); - } - - /** Visits a ``long long`` argument. **/ - Result visit_long_long(LongLong value) { - return FMT_DISPATCH(visit_any_int(value)); - } - - /** Visits an ``unsigned`` argument. **/ - Result visit_uint(unsigned value) { - return FMT_DISPATCH(visit_any_int(value)); - } - - /** Visits an ``unsigned long long`` argument. **/ - Result visit_ulong_long(ULongLong value) { - return FMT_DISPATCH(visit_any_int(value)); - } - - /** Visits a ``bool`` argument. **/ - Result visit_bool(bool value) { - return FMT_DISPATCH(visit_any_int(value)); - } - - /** Visits a ``char`` or ``wchar_t`` argument. **/ - Result visit_char(int value) { - return FMT_DISPATCH(visit_any_int(value)); - } - - /** Visits an argument of any integral type. **/ - template - Result visit_any_int(T) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - /** Visits a ``double`` argument. **/ - Result visit_double(double value) { - return FMT_DISPATCH(visit_any_double(value)); - } - - /** Visits a ``long double`` argument. **/ - Result visit_long_double(long double value) { - return FMT_DISPATCH(visit_any_double(value)); - } - - /** Visits a ``double`` or ``long double`` argument. **/ - template - Result visit_any_double(T) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - /** Visits a null-terminated C string (``const char *``) argument. **/ - Result visit_cstring(const char *) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - /** Visits a string argument. **/ - Result visit_string(Arg::StringValue) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - /** Visits a wide string argument. **/ - Result visit_wstring(Arg::StringValue) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - /** Visits a pointer argument. **/ - Result visit_pointer(const void *) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - /** Visits an argument of a custom (user-defined) type. **/ - Result visit_custom(Arg::CustomValue) { - return FMT_DISPATCH(visit_unhandled_arg()); - } - - Result operator()(int value) { - return FMT_DISPATCH(visit_int(value)); - } - - Result operator()(unsigned value) { - return FMT_DISPATCH(visit_uint(value)); - } - - Result operator()(fmt::LongLong value) { - return FMT_DISPATCH(visit_long_long(value)); - } - - Result operator()(fmt::ULongLong value) { - return FMT_DISPATCH(visit_ulong_long(value)); - } - - Result operator()(bool value) { - return FMT_DISPATCH(visit_bool(value)); - } - - Result operator()(wchar_t value) { - return FMT_DISPATCH(visit_char(value)); - } - - Result operator()(double value) { - return FMT_DISPATCH(visit_double(value)); - } - - Result operator()(long double value) { - return FMT_DISPATCH(visit_long_double(value)); - } - - Result operator()(const char *value) { - return FMT_DISPATCH(visit_cstring(value)); - } - - Result operator()(format_arg::StringValue value) { - return FMT_DISPATCH(visit_string(value)); - } - - Result operator()(format_arg::StringValue value) { - return FMT_DISPATCH(visit_wstring(value)); - } - - Result operator()(const void *value) { - return FMT_DISPATCH(visit_pointer(value)); - } - - Result operator()(format_arg::CustomValue value) { - return FMT_DISPATCH(visit_custom(value)); - } -}; - enum Alignment { ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC }; @@ -2041,7 +1874,7 @@ void ArgMap::init(const basic_format_args &args) { } template -class ArgFormatterBase : public ArgVisitor { +class ArgFormatterBase { private: BasicWriter &writer_; FormatSpec &spec_; @@ -2092,16 +1925,16 @@ class ArgFormatterBase : public ArgVisitor { : writer_(w), spec_(s) {} template - void visit_any_int(T value) { writer_.write_int(value, spec_); } + typename std::enable_if::value>::type + operator()(T value) { writer_.write_int(value, spec_); } template - void visit_any_double(T value) { writer_.write_double(value, spec_); } - - using ArgVisitor::operator(); + typename std::enable_if::value>::type + operator()(T value) { writer_.write_double(value, spec_); } void operator()(bool value) { if (spec_.type_) - return visit_any_int(value); + return (*this)(value ? 1 : 0); write(value); } @@ -2222,23 +2055,7 @@ class format_context_base { }; } // namespace internal -/** - \rst - An argument formatter based on the `curiously recurring template pattern - `_. - - To use `~fmt::BasicArgFormatter` define a subclass that implements some or - all of the visit methods with the same signatures as the methods in - `~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. - Pass the subclass as the *Impl* template parameter. When a formatting - function processes an argument, it will dispatch to a visit method - specific to the argument type. For example, if the argument type is - ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass - will be called. If the subclass doesn't contain a method with this signature, - then a corresponding method of `~fmt::BasicArgFormatter` or its superclass - will be called. - \endrst - */ +/** An argument formatter. */ template class BasicArgFormatter : public internal::ArgFormatterBase { private: @@ -2257,8 +2074,10 @@ class BasicArgFormatter : public internal::ArgFormatterBase { FormatSpec &spec) : internal::ArgFormatterBase(writer, spec), ctx_(ctx) {} + using internal::ArgFormatterBase::operator(); + /** Formats an argument of a custom (user-defined) type. */ - void visit_custom(internal::Arg::CustomValue c) { + void operator()(internal::Arg::CustomValue c) { c.format(&this->writer(), c.value, &ctx_); } }; diff --git a/test/custom-formatter-test.cc b/test/custom-formatter-test.cc index 779c1ea2..9c568523 100644 --- a/test/custom-formatter-test.cc +++ b/test/custom-formatter-test.cc @@ -21,10 +21,12 @@ class CustomArgFormatter fmt::FormatSpec &s) : fmt::BasicArgFormatter(w, ctx, s) {} - void visit_double(double value) { + using fmt::BasicArgFormatter::operator(); + + void operator()(double value) { if (round(value * pow(10, spec().precision())) == 0) value = 0; - fmt::BasicArgFormatter::visit_double(value); + fmt::BasicArgFormatter::operator()(value); } }; diff --git a/test/format-test.cc b/test/format-test.cc index e7e72a1d..2ce9d7f3 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1621,16 +1621,23 @@ TEST(FormatTest, Enum) { class MockArgFormatter : public fmt::internal::ArgFormatterBase { + private: + MOCK_METHOD1(call, void (int value)); + public: typedef fmt::internal::ArgFormatterBase Base; MockArgFormatter(fmt::Writer &w, fmt::format_context &ctx, fmt::FormatSpec &s) : fmt::internal::ArgFormatterBase(w, s) { - EXPECT_CALL(*this, visit_int(42)); + EXPECT_CALL(*this, call(42)); } - MOCK_METHOD1(visit_int, void (int value)); + using Base::operator(); + + void operator()(int value) { call(value); } + + void operator()(fmt::internal::Arg::CustomValue) {} }; void custom_vformat(fmt::CStringRef format_str, fmt::format_args args) { diff --git a/test/util-test.cc b/test/util-test.cc index 7bca57e4..2b144b95 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -605,23 +605,23 @@ struct Result { Result(const wchar_t *s) : arg(make_arg(s)) {} }; -struct TestVisitor : fmt::ArgVisitor { - Result visit_int(int value) { return value; } - Result visit_uint(unsigned value) { return value; } - Result visit_long_long(fmt::LongLong value) { return value; } - Result visit_ulong_long(fmt::ULongLong value) { return value; } - Result visit_double(double value) { return value; } - Result visit_long_double(long double value) { return value; } - Result visit_char(int value) { return static_cast(value); } - Result visit_cstring(const char *s) { return s; } - Result visit_string(fmt::internal::Arg::StringValue s) { +struct TestVisitor { + Result operator()(int value) { return value; } + Result operator()(unsigned value) { return value; } + Result operator()(fmt::LongLong value) { return value; } + Result operator()(fmt::ULongLong value) { return value; } + Result operator()(double value) { return value; } + Result operator()(long double value) { return value; } + Result operator()(wchar_t value) { return static_cast(value); } + Result operator()(const char *s) { return s; } + Result operator()(fmt::format_arg::StringValue s) { return s.value; } - Result visit_wstring(fmt::internal::Arg::StringValue s) { + Result operator()(fmt::format_arg::StringValue s) { return s.value; } - Result visit_pointer(const void *p) { return p; } - Result visit_custom(fmt::internal::Arg::CustomValue c) { + Result operator()(const void *p) { return p; } + Result operator()(fmt::format_arg::CustomValue c) { return *static_cast(c.value); } }; @@ -658,55 +658,6 @@ TEST(ArgVisitorTest, VisitAll) { EXPECT_EQ(&t, result.arg.custom.value); } -struct TestAnyVisitor : fmt::ArgVisitor { - template - Result visit_any_int(T value) { return value; } - - template - Result visit_any_double(T value) { return value; } -}; - -#undef EXPECT_RESULT -#define EXPECT_RESULT(type_code, value) { \ - Result result = visit(TestAnyVisitor(), make_arg(value)); \ - EXPECT_EQ(Arg::type_code, result.arg.type); \ - EXPECT_EQ(value, ArgInfo::get(result.arg)); \ -} - -TEST(ArgVisitorTest, VisitAny) { - EXPECT_RESULT(INT, 42); - EXPECT_RESULT(UINT, 42u); - EXPECT_RESULT(LONG_LONG, 42ll); - EXPECT_RESULT(ULONG_LONG, 42ull); - EXPECT_RESULT(DOUBLE, 4.2); - EXPECT_RESULT(LONG_DOUBLE, 4.2l); -} - -struct TestUnhandledVisitor : - fmt::ArgVisitor { - const char *visit_unhandled_arg() { return "test"; } -}; - -#define EXPECT_UNHANDLED(value) \ - EXPECT_STREQ("test", visit(TestUnhandledVisitor(), make_arg(value))); - -TEST(ArgVisitorTest, VisitUnhandledArg) { - EXPECT_UNHANDLED(42); - EXPECT_UNHANDLED(42u); - EXPECT_UNHANDLED(42ll); - EXPECT_UNHANDLED(42ull); - EXPECT_UNHANDLED(4.2); - EXPECT_UNHANDLED(4.2l); - EXPECT_UNHANDLED('x'); - const char STR[] = "abc"; - EXPECT_UNHANDLED(STR); - const wchar_t WSTR[] = L"abc"; - EXPECT_UNHANDLED(WSTR); - const void *p = STR; - EXPECT_UNHANDLED(p); - EXPECT_UNHANDLED(::Test()); -} - TEST(ArgVisitorTest, VisitInvalidArg) { Arg arg = Arg(); arg.type = static_cast(Arg::NONE);