diff --git a/include/fmt/core.h b/include/fmt/core.h index 77ff089b..0986789f 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -616,7 +616,8 @@ FMT_MAKE_VALUE(pointer_type, std::nullptr_t, const void*) // formatting of "[const] volatile char *" which is printed as bool by // iostreams. template -typed_value make_value(const T *) { +typename std::enable_if::value>::type + make_value(const T *) { static_assert(!sizeof(T), "formatting of non-void pointers is disallowed"); } @@ -1240,12 +1241,12 @@ inline std::string format(string_view format_str, const Args & ... args) { // This should be just // return vformat(format_str, make_format_args(args...)); // but gcc has trouble optimizing the latter, so break it down. - format_arg_store as(args...); + format_arg_store as{args...}; return vformat(format_str, as); } template inline std::wstring format(wstring_view format_str, const Args & ... args) { - format_arg_store as(args...); + format_arg_store as{args...}; return vformat(format_str, as); } @@ -1286,7 +1287,7 @@ FMT_API void vprint(wstring_view format_str, wformat_args args); */ template inline void print(string_view format_str, const Args & ... args) { - format_arg_store as(args...); + format_arg_store as{args...}; vprint(format_str, as); } diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index 14619364..5daa272b 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -140,13 +140,13 @@ inline void vprint(std::basic_ostream &os, template inline void print(std::ostream &os, string_view format_str, const Args & ... args) { - vprint(os, format_str, make_format_args(args...)); + vprint(os, format_str, make_format_args(args...)); } template inline void print(std::wostream &os, wstring_view format_str, const Args & ... args) { - vprint(os, format_str, make_format_args(args...)); + vprint(os, format_str, make_format_args(args...)); } FMT_END_NAMESPACE diff --git a/include/fmt/printf.h b/include/fmt/printf.h index 5a396964..e9a81669 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -215,7 +215,9 @@ class basic_printf_context; */ template class printf_arg_formatter: - public internal::function, public internal::arg_formatter_base { + public internal::function< + typename internal::arg_formatter_base::iterator>, + public internal::arg_formatter_base { private: typedef typename Range::value_type char_type; typedef decltype(internal::declval().begin()) iterator; @@ -627,7 +629,7 @@ template inline int fprintf(std::FILE *f, string_view format_str, const Args & ... args) { auto vargs = make_format_args< typename printf_context::type>(args...); - return vfprintf(f, format_str, vargs); + return vfprintf(f, format_str, vargs); } template diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 3e8480a1..c04488de 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -34,18 +34,20 @@ template struct formatting_range : formatting_base { static FMT_CONSTEXPR_DECL const std::size_t range_length_limit = FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the range. - Char prefix = '{'; - Char delimiter = ','; - Char postfix = '}'; + Char prefix; + Char delimiter; + Char postfix; + formatting_range() : prefix('{'), delimiter(','), postfix('}') {} static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true; static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false; }; template struct formatting_tuple : formatting_base { - Char prefix = '('; - Char delimiter = ','; - Char postfix = ')'; + Char prefix; + Char delimiter; + Char postfix; + formatting_tuple() : prefix('('), delimiter(','), postfix(')') {} static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true; static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false; }; @@ -54,9 +56,8 @@ namespace internal { template void copy(const RangeT &range, OutputIterator out) { - for (const auto &it : range) { - *out++ = it; - } + for (auto it = range.begin(), end = range.end(); it != end; ++it) + *out++ = *it; } template @@ -83,7 +84,7 @@ class is_like_std_string { public: static FMT_CONSTEXPR_DECL const bool value = - !std::is_void(nullptr))>::value; + !std::is_void(FMT_NULL))>::value; }; template @@ -95,8 +96,8 @@ struct is_range_ : std::false_type {}; template struct is_range_().begin()), - decltype(std::declval().end())>, + conditional_helper().begin()), + decltype(internal::declval().end())>, void>::type> : std::true_type {}; template @@ -111,13 +112,13 @@ class is_tuple_like_ { template static auto check(U *p) -> decltype(std::tuple_size::value, - std::declval::type>(), int()); + internal::declval::type>(), int()); template static void check(...); public: static FMT_CONSTEXPR_DECL const bool value = - !std::is_void(nullptr))>::value; + !std::is_void(FMT_NULL))>::value; }; template @@ -125,7 +126,16 @@ struct is_tuple_like { static FMT_CONSTEXPR_DECL const bool value = is_tuple_like_::value && !is_range_::value; }; +} // namespace internal +#if FMT_HAS_FEATURE(__cpp_lib_integer_sequence) +# define FMT_USE_INTEGER_SEQUENCE 1 +#else +# define FMT_USE_INTEGER_SEQUENCE 0 +#endif + +#if FMT_USE_INTEGER_SEQUENCE +namespace internal { template void for_each(std::index_sequence, Tuple &&tup, F &&f) noexcept { using std::get; @@ -183,6 +193,7 @@ struct formatter struct formatter< RangeT, Char, @@ -196,11 +207,12 @@ struct formatter< RangeT, Char, } template - auto format(const RangeT &values, FormatContext &ctx) -> decltype(ctx.out()) { + typename FormatContext::iterator format( + const RangeT &values, FormatContext &ctx) { auto out = ctx.out(); internal::copy(formatting.prefix, out); std::size_t i = 0; - for (const auto &it : values) { + for (auto it = values.begin(), end = values.end(); it != end; ++it) { if (i > 0) { if (formatting.add_prepostfix_space) { *out++ = ' '; @@ -208,9 +220,9 @@ struct formatter< RangeT, Char, internal::copy(formatting.delimiter, out); } if (formatting.add_delimiter_spaces && i > 0) { - format_to(out, " {}", it); + format_to(out, " {}", *it); } else { - format_to(out, "{}", it); + format_to(out, "{}", *it); } if (++i > formatting.range_length_limit) { format_to(out, " ... "); diff --git a/test/format-test.cc b/test/format-test.cc index daa0b676..0044390e 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1394,7 +1394,8 @@ TEST(FormatTest, FixedEnum) { typedef fmt::back_insert_range buffer_range; class mock_arg_formatter: - public fmt::internal::function, + public fmt::internal::function< + fmt::internal::arg_formatter_base::iterator>, public fmt::internal::arg_formatter_base { private: MOCK_METHOD1(call, void (int value)); diff --git a/test/ranges-test.cc b/test/ranges-test.cc index 76c37a11..c27833f2 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -30,6 +30,7 @@ TEST(RangesTest, FormatVector2) { EXPECT_EQ("{{1, 2}, {3, 5}, {7, 11}}", ivf); } +#if FMT_USE_INTEGER_SEQUENCE TEST(RangesTest, FormatMap) { std::map simap{{"one", 1}, {"two", 2}}; EXPECT_EQ("{(one, 1), (two, 2)}", fmt::format("{}", simap)); @@ -46,7 +47,7 @@ TEST(RangesTest, FormatTuple) { EXPECT_EQ("(42, 3.14159, this is tuple)", fmt::format("{}", tu1)); } -/// check if 'if constexpr' is supported. +/// Check if 'if constexpr' is supported. #if (__cplusplus > 201402L) || \ (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910) @@ -86,3 +87,4 @@ TEST(RangesTest, FormatStruct) { #endif // (__cplusplus > 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG > // 201402L && _MSC_VER >= 1910) +#endif // FMT_USE_INTEGER_SEQUENCE diff --git a/test/util-test.cc b/test/util-test.cc index 5bba7736..07509118 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -397,13 +397,14 @@ TEST(FixedBufferTest, BufferOverflow) { EXPECT_THROW_MSG(buffer.resize(11), std::runtime_error, "buffer overflow"); } +struct uint32_pair { + uint32_t u[2]; +}; + TEST(UtilTest, BitCast) { - struct S { - uint32_t u[2]; - }; - auto s = fmt::internal::bit_cast(uint64_t(42)); + auto s = fmt::internal::bit_cast(uint64_t{42}); EXPECT_EQ(fmt::internal::bit_cast(s), 42u); - s = fmt::internal::bit_cast(uint64_t(~0ull)); + s = fmt::internal::bit_cast(uint64_t(~0ull)); EXPECT_EQ(fmt::internal::bit_cast(s), ~0ull); }