diff --git a/fmt/format.h b/fmt/format.h index 4093f3ea..3bf486f0 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -1212,8 +1212,7 @@ class MakeValue : public Arg { MakeValue() {} #define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \ - MakeValue(Type value) { field = rhs; } \ - static uint64_t type(Type) { return Arg::TYPE; } + MakeValue(Type value) { field = rhs; } #define FMT_MAKE_VALUE(Type, field, TYPE) \ FMT_MAKE_VALUE_(Type, field, TYPE, value) @@ -1232,9 +1231,6 @@ class MakeValue : public Arg { else long_long_value = value; } - static uint64_t type(long) { - return sizeof(long) == sizeof(int) ? Arg::INT : Arg::LONG_LONG; - } MakeValue(unsigned long value) { if (const_check(sizeof(unsigned long) == sizeof(unsigned))) @@ -1242,10 +1238,6 @@ class MakeValue : public Arg { else ulong_long_value = value; } - static uint64_t type(unsigned long) { - return sizeof(unsigned long) == sizeof(unsigned) ? - Arg::UINT : Arg::ULONG_LONG; - } FMT_MAKE_VALUE(LongLong, long_long_value, LONG_LONG) FMT_MAKE_VALUE(ULongLong, ulong_long_value, ULONG_LONG) @@ -1260,12 +1252,10 @@ class MakeValue : public Arg { MakeValue(typename WCharHelper::Supported value) { int_value = value; } - static uint64_t type(wchar_t) { return Arg::CHAR; } #endif #define FMT_MAKE_STR_VALUE(Type, TYPE) \ - MakeValue(Type value) { set_string(value); } \ - static uint64_t type(Type) { return Arg::TYPE; } + MakeValue(Type value) { set_string(value); } FMT_MAKE_VALUE(char *, string.value, CSTRING) FMT_MAKE_VALUE(const char *, string.value, CSTRING) @@ -1280,8 +1270,7 @@ class MakeValue : public Arg { #define FMT_MAKE_WSTR_VALUE(Type, TYPE) \ MakeValue(typename WCharHelper::Supported value) { \ set_string(value); \ - } \ - static uint64_t type(Type) { return Arg::TYPE; } + } FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING) FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING) @@ -1305,20 +1294,74 @@ class MakeValue : public Arg { int_value = value; } - template - static uint64_t type(const T &) { - return ConvertToInt::value ? Arg::INT : Arg::CUSTOM; - } - // Additional template param `Char_` is needed here because make_type always // uses char. template MakeValue(const NamedArg &value) { pointer = &value; } - - template - static uint64_t type(const NamedArg &) { return Arg::NAMED_ARG; } }; +template +struct IsNamedArg : std::false_type {}; + +template +struct IsNamedArg< NamedArg > : std::true_type {}; + +typedef Value::Type Type; + +template +constexpr Type gettype() { + return IsNamedArg::value ? + Arg::NAMED_ARG : (ConvertToInt::value ? Arg::INT : Arg::CUSTOM); +} + +template <> constexpr Type gettype() { return Arg::BOOL; } +template <> constexpr Type gettype() { return Arg::INT; } +template <> constexpr Type gettype() { return Arg::UINT; } +template <> constexpr Type gettype() { return Arg::INT; } +template <> constexpr Type gettype() { return Arg::UINT; } +template <> constexpr Type gettype() { + return sizeof(long) == sizeof(int) ? Arg::INT : Arg::LONG_LONG; +} +template <> constexpr Type gettype() { + return sizeof(unsigned long) == sizeof(unsigned) ? + Arg::UINT : Arg::ULONG_LONG; +} +template <> constexpr Type gettype() { return Arg::LONG_LONG; } +template <> constexpr Type gettype() { return Arg::ULONG_LONG; } +template <> constexpr Type gettype() { return Arg::DOUBLE; } +template <> constexpr Type gettype() { return Arg::DOUBLE; } +template <> constexpr Type gettype() { return Arg::LONG_DOUBLE; } +template <> constexpr Type gettype() { return Arg::INT; } +template <> constexpr Type gettype() { return Arg::UINT; } +template <> constexpr Type gettype() { return Arg::CHAR; } + +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +template <> constexpr Type gettype() { return Arg::CHAR; } +#endif + +template <> constexpr Type gettype() { return Arg::CSTRING; } +template <> constexpr Type gettype() { return Arg::CSTRING; } +template <> constexpr Type gettype() { return Arg::CSTRING; } +template <> constexpr Type gettype() { + return Arg::CSTRING; +} +template <> constexpr Type gettype() { return Arg::CSTRING; } +template <> constexpr Type gettype() { + return Arg::CSTRING; +} +template <> constexpr Type gettype() { return Arg::STRING; } +template <> constexpr Type gettype() { return Arg::STRING; } +template <> constexpr Type gettype() { return Arg::CSTRING; } +template <> constexpr Type gettype() { return Arg::WSTRING; } +template <> constexpr Type gettype() { return Arg::WSTRING; } +template <> constexpr Type gettype() { return Arg::WSTRING; } +template <> constexpr Type gettype() { return Arg::WSTRING; } +template <> constexpr Type gettype() { return Arg::POINTER; } +template <> constexpr Type gettype() { return Arg::POINTER; } + +template +constexpr Type type() { return gettype::type>(); } + template class MakeArg : public Arg { public: @@ -1329,7 +1372,7 @@ public: template MakeArg(const T &value) : Arg(MakeValue(value)) { - type = static_cast(MakeValue::type(value)); + type = internal::type(); } }; @@ -2087,13 +2130,15 @@ class BasicFormatter : private internal::FormatterBase { # define FMT_GEN15(f) FMT_GEN14(f), f(14) namespace internal { -inline uint64_t make_type() { return 0; } -template -inline uint64_t make_type(const T &arg) { - return MakeValue< BasicFormatter >::type(arg); +template +constexpr uint64_t make_type() { + return type() | (make_type() << 4); } +template <> +constexpr uint64_t make_type() { return 0; } + template class format_arg_store { private: @@ -2102,13 +2147,15 @@ class format_arg_store { typedef typename std::conditional::type value_type; - // If the arguments are not packed we add one more element to mark the end. + // If the arguments are not packed, add one more element to mark the end. std::array data_; template friend format_arg_store make_format_args(const A & ... args); public: + static const uint64_t TYPES = make_type(); + template format_arg_store(const Args &... args, Formatter *) : data_{MakeValue(args)...} {} @@ -2121,11 +2168,6 @@ inline format_arg_store make_format_args(const Args & ... args) { Formatter *f = nullptr; return format_arg_store(args..., f); } - -template -inline uint64_t make_type(const Arg &first, const Args & ... tail) { - return make_type(first) | (make_type(tail...) << 4); -} } // namespace internal # define FMT_MAKE_TEMPLATE_ARG(n) typename T##n @@ -2141,7 +2183,7 @@ inline uint64_t make_type(const Arg &first, const Args & ... tail) { template \ void func(arg_type arg0, const Args & ... args) { \ auto store = fmt::internal::make_format_args< fmt::BasicFormatter >(args...); \ - func(arg0, fmt::format_args(fmt::internal::make_type(args...), store.data())); \ + func(arg0, fmt::format_args(store.TYPES, store.data())); \ } // Defines a variadic constructor. @@ -2149,7 +2191,7 @@ inline uint64_t make_type(const Arg &first, const Args & ... tail) { template \ ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \ auto store = internal::make_format_args< fmt::BasicFormatter >(args...); \ - func(arg0, arg1, fmt::format_args(fmt::internal::make_type(args...), store.data())); \ + func(arg0, arg1, fmt::format_args(store.TYPES, store.data())); \ } // Generates a comma-separated list with results of applying f to pairs @@ -3288,7 +3330,7 @@ void arg(WStringRef, const internal::NamedArg&) FMT_DELETED_OR_UNDEFINED; const Args & ... args) { \ auto store = fmt::internal::make_format_args< fmt::BasicFormatter >(args...); \ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \ - fmt::format_args(fmt::internal::make_type(args...), store.data())); \ + fmt::format_args(store.TYPES, store.data())); \ } /** diff --git a/test/util-test.cc b/test/util-test.cc index 376ea128..6c1a2c0d 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -72,7 +72,7 @@ template Arg make_arg(const T &value) { typedef fmt::internal::MakeValue< fmt::BasicFormatter > MakeValue; Arg arg = MakeValue(value); - arg.type = static_cast(MakeValue::type(value)); + arg.type = fmt::internal::type(); return arg; } } // namespace