From a721319e3aed92fea05a19a27a155d635c74a7fe Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sat, 24 Oct 2015 20:16:46 +0200 Subject: [PATCH 1/2] Add MakeArg constructor for Arg --- format.h | 63 +++++++++++++++++++++++++------------------------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/format.h b/format.h index 9a7e0253..f0d64967 100644 --- a/format.h +++ b/format.h @@ -1211,17 +1211,27 @@ class MakeValue : public Arg { static uint64_t type(const NamedArg &) { return Arg::NAMED_ARG; } }; +template +class MakeArg : public Arg { +public: + MakeArg() { + type = Arg::NONE; + } + + template + MakeArg(const T &value) + : Arg(MakeValue(value)) { + type = static_cast(MakeValue::type(value)); + } +}; + 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(MakeArg< BasicFormatter >(value)), name(argname) {} }; #define FMT_DISPATCH(call) static_cast(this)->call @@ -1931,44 +1941,29 @@ inline uint64_t make_type(const Arg &first, const Args & ... tail) { return make_type(first) | (make_type(tail...) << 4); } -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< BasicFormatter >::type(arg)); - do_set_types(args + 1, tail...); +template +inline void store_args(Arg *args) { + *args = MakeArg(); } -template -inline void set_types(Arg *array, const Args & ... args) { - if (check(sizeof...(Args) > ArgList::MAX_PACKED_ARGS)) - do_set_types(array, args...); - array[sizeof...(Args)].type = Arg::NONE; +template +inline void store_args(Arg *args, const T &arg, const Args & ... tail) { + *args = MakeArg(arg); + store_args(args + 1, tail...); } -template -inline void set_types(Value *, const Args & ...) { - // Do nothing as types are passed separately from values. -} - -template +template inline void store_args(Value *) {} -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); +template +inline void store_args(Value *args, const T &arg, const Args & ... tail) { + *args = MakeValue(arg); store_args(args + 1, tail...); } 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...); return ArgList(make_type(args...), array); } @@ -2944,10 +2939,8 @@ void format(BasicFormatter &f, const Char *&format_str, const T &value) { output << value; BasicStringRef str(&buffer[0], format_buf.size()); - typedef internal::MakeValue< BasicFormatter > MakeValue; - internal::Arg arg = MakeValue(str); - arg.type = static_cast(MakeValue::type(str)); - format_str = f.format(format_str, arg); + typedef internal::MakeArg< BasicFormatter > MakeArg; + format_str = f.format(format_str, MakeArg(str)); } // Reports a system error without throwing an exception. From b098306839f669aa93f3d5de492f769fe3950dd4 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sat, 12 Dec 2015 17:12:29 +0100 Subject: [PATCH 2/2] Replace template recursion with array initialization --- format.h | 72 ++++++++++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/format.h b/format.h index f0d64967..15c522f9 100644 --- a/format.h +++ b/format.h @@ -1923,16 +1923,23 @@ inline uint64_t make_type(const T &arg) { return MakeValue< BasicFormatter >::type(arg); } -template -struct ArgArray { - // Computes the argument array size by adding 1 to N, which is the number of - // arguments, if N is zero, because array of zero size is invalid, or if N - // is greater than ArgList::MAX_PACKED_ARGS to accommodate for an extra - // argument that marks the end of the list. - enum { SIZE = N + (N == 0 || N >= ArgList::MAX_PACKED_ARGS ? 1 : 0) }; +template +struct ArgArray; - typedef typename Conditional< - (N < ArgList::MAX_PACKED_ARGS), Value, Arg>::type Type[SIZE]; +template +struct ArgArray { + typedef Value Type[N > 0 ? N : 1]; + + template + static Value make(const T &value) { return MakeValue(value); } +}; + +template +struct ArgArray { + typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE + + template + static Arg make(const T &value) { return MakeArg(value); } }; #if FMT_USE_VARIADIC_TEMPLATES @@ -1941,32 +1948,6 @@ inline uint64_t make_type(const Arg &first, const Args & ... tail) { return make_type(first) | (make_type(tail...) << 4); } -template -inline void store_args(Arg *args) { - *args = MakeArg(); -} - -template -inline void store_args(Arg *args, const T &arg, const Args & ... tail) { - *args = MakeArg(arg); - store_args(args + 1, tail...); -} - -template -inline void store_args(Value *) {} - -template -inline void store_args(Value *args, const T &arg, const Args & ... tail) { - *args = MakeValue(arg); - store_args(args + 1, tail...); -} - -template -ArgList make_arg_list(typename ArgArray::Type array, - const Args & ... args) { - store_args(array, args...); - return ArgList(make_type(args...), array); -} #else struct ArgType { @@ -2034,18 +2015,20 @@ class FormatBuf : public std::basic_streambuf { # define FMT_VARIADIC_VOID(func, arg_type) \ template \ void func(arg_type arg0, const Args & ... args) { \ - typename fmt::internal::ArgArray::Type array; \ - func(arg0, fmt::internal::make_arg_list< \ - fmt::BasicFormatter >(array, args...)); \ + typedef fmt::internal::ArgArray ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make >(args)...}; \ + func(arg0, fmt::ArgList(fmt::internal::make_type(args...), array)); \ } // Defines a variadic constructor. # define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \ 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< \ - fmt::BasicFormatter >(array, args...)); \ + typedef fmt::internal::ArgArray ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make >(args)...}; \ + func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \ } #else @@ -3264,10 +3247,11 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; template \ ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \ const Args & ... args) { \ - typename fmt::internal::ArgArray::Type array; \ + typedef fmt::internal::ArgArray ArgArray; \ + typename ArgArray::Type array{ \ + ArgArray::template make >(args)...}; \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ - fmt::internal::make_arg_list< \ - fmt::BasicFormatter >(array, args...)); \ + fmt::ArgList(fmt::internal::make_type(args...), array)); \ } #else // Defines a wrapper for a function taking __VA_ARGS__ arguments