diff --git a/format.h b/format.h index 568123d8..362c449b 100644 --- a/format.h +++ b/format.h @@ -1021,8 +1021,11 @@ template<> struct Not { enum { value = 1 }; }; // Makes an Arg object from any type. -template +template class MakeValue : public Arg { + public: + typedef typename Formatter::Char Char; + private: // The following two methods are private to disallow formatting of // arbitrary pointers. If you want to output a pointer cast it to @@ -1060,7 +1063,7 @@ class MakeValue : public Arg { template static void format_custom_arg( void *formatter, const void *arg, void *format_str_ptr) { - format(*static_cast*>(formatter), + format(*static_cast(formatter), *static_cast(format_str_ptr), *static_cast(arg)); } @@ -1166,7 +1169,7 @@ class MakeValue : public Arg { } // Additional template param `Char_` is needed here because make_type always - // uses MakeValue. + // uses char. template MakeValue(const NamedArg &value) { pointer = &value; } @@ -1178,10 +1181,12 @@ template struct NamedArg : Arg { BasicStringRef name; + typedef internal::MakeValue< BasicFormatter > MakeValue; + template NamedArg(BasicStringRef argname, const T &value) - : Arg(MakeValue(value)), name(argname) { - type = static_cast(MakeValue::type(value)); + : Arg(MakeValue(value)), name(argname) { + type = static_cast(MakeValue::type(value)); } }; @@ -1455,8 +1460,11 @@ class PrintfFormatter : private FormatterBase { } // namespace internal // A formatter. -template +template class BasicFormatter : private internal::FormatterBase { + public: + typedef CharType Char; + private: BasicWriter &writer_; internal::ArgMap map_; @@ -1730,7 +1738,9 @@ namespace internal { inline uint64_t make_type() { return 0; } template -inline uint64_t make_type(const T &arg) { return MakeValue::type(arg); } +inline uint64_t make_type(const T &arg) { + return MakeValue< BasicFormatter >::type(arg); +} template struct ArgArray { @@ -1754,7 +1764,8 @@ inline void do_set_types(Arg *) {} template inline void do_set_types(Arg *args, const T &arg, const Args & ... tail) { - args->type = static_cast(MakeValue::type(arg)); + args->type = static_cast( + MakeValue< BasicFormatter >::type(arg)); do_set_types(args + 1, tail...); } @@ -1770,24 +1781,24 @@ inline void set_types(Value *, const Args & ...) { // Do nothing as types are passed separately from values. } -template +template inline void store_args(Value *) {} -template +template inline void store_args(Arg *args, const T &arg, const Args & ... tail) { // Assign only the Value subobject of Arg and don't overwrite type (if any) // that is assigned by set_types. Value &value = *args; - value = MakeValue(arg); - store_args(args + 1, tail...); + value = MakeValue(arg); + store_args(args + 1, tail...); } -template +template ArgList make_arg_list(typename ArgArray::Type array, const Args & ... args) { if (check(sizeof...(Args) >= ArgList::MAX_PACKED_ARGS)) set_types(array, args...); - store_args(array, args...); + store_args(array, args...); return ArgList(make_type(args...), array); } #else @@ -1847,8 +1858,10 @@ class FormatBuf : public std::basic_streambuf { # define FMT_MAKE_TEMPLATE_ARG(n) typename T##n # define FMT_MAKE_ARG_TYPE(n) T##n # define FMT_MAKE_ARG(n) const T##n &v##n -# define FMT_ASSIGN_char(n) arr[n] = fmt::internal::MakeValue(v##n) -# define FMT_ASSIGN_wchar_t(n) arr[n] = fmt::internal::MakeValue(v##n) +# define FMT_ASSIGN_char(n) \ + arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) +# define FMT_ASSIGN_wchar_t(n) \ + arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) #if FMT_USE_VARIADIC_TEMPLATES // Defines a variadic function returning void. @@ -1856,7 +1869,8 @@ class FormatBuf : public std::basic_streambuf { template \ void func(arg_type arg0, const Args & ... args) { \ typename fmt::internal::ArgArray::Type array; \ - func(arg0, fmt::internal::make_arg_list(array, args...)); \ + func(arg0, fmt::internal::make_arg_list< \ + fmt::BasicFormatter >(array, args...)); \ } // Defines a variadic constructor. @@ -1864,12 +1878,14 @@ class FormatBuf : public std::basic_streambuf { template \ ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \ typename fmt::internal::ArgArray::Type array; \ - func(arg0, arg1, fmt::internal::make_arg_list(array, args...)); \ + func(arg0, arg1, fmt::internal::make_arg_list< \ + fmt::BasicFormatter >(array, args...)); \ } #else -# define FMT_MAKE_REF(n) fmt::internal::MakeValue(v##n) +# define FMT_MAKE_REF(n) \ + fmt::internal::MakeValue< fmt::BasicFormatter >(v##n) # define FMT_MAKE_REF2(n) v##n // Defines a wrapper for a function taking one argument of type arg_type @@ -2735,9 +2751,9 @@ void format(BasicFormatter &f, const Char *&format_str, const T &value) { output << value; BasicStringRef str(&buffer[0], format_buf.size()); - internal::Arg arg = internal::MakeValue(str); - arg.type = static_cast( - internal::MakeValue::type(str)); + typedef internal::MakeValue< BasicFormatter > MakeValue; + internal::Arg arg = MakeValue(str); + arg.type = static_cast(MakeValue::type(str)); format_str = f.format(format_str, arg); } @@ -3062,7 +3078,8 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; const Args & ... args) { \ typename fmt::internal::ArgArray::Type array; \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ - fmt::internal::make_arg_list(array, args...)); \ + fmt::internal::make_arg_list< \ + fmt::BasicFormatter >(array, args...)); \ } #else // Defines a wrapper for a function taking __VA_ARGS__ arguments diff --git a/test/util-test.cc b/test/util-test.cc index 03557d64..2aa8245b 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -69,9 +69,9 @@ std::basic_ostream &operator<<(std::basic_ostream &os, Test) { template Arg make_arg(const T &value) { - Arg arg = fmt::internal::MakeValue(value); - arg.type = static_cast( - fmt::internal::MakeValue::type(value)); + typedef fmt::internal::MakeValue< fmt::BasicFormatter > MakeValue; + Arg arg = MakeValue(value); + arg.type = static_cast(MakeValue::type(value)); return arg; } } // namespace @@ -575,6 +575,23 @@ TEST(UtilTest, ArgList) { EXPECT_EQ(Arg::NONE, args[1].type); } +struct CustomFormatter { + typedef char Char; +}; + +void format(CustomFormatter &, const char *&s, const Test &) { + s = "custom_format"; +} + +TEST(UtilTest, MakeValueWithCustomFormatter) { + ::Test t; + Arg arg = fmt::internal::MakeValue(t); + CustomFormatter formatter; + const char *s = ""; + arg.custom.format(&formatter, &t, &s); + EXPECT_STREQ("custom_format", s); +} + struct Result { Arg arg;