diff --git a/include/fmt/format.h b/include/fmt/format.h index 0635f3d3..c7493d6e 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -196,23 +196,6 @@ struct is_contiguous> namespace detail { -#ifdef FMT_USE_BITINT -// Use the provided definition. -#elif FMT_CLANG_VERSION >= 1500 && !defined(__CUDACC__) -# define FMT_USE_BITINT 1 -#else -# define FMT_USE_BITINT 0 -#endif - -#if FMT_USE_BITINT -FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension") -template using bitint = _BitInt(N); -template using ubitint = unsigned _BitInt(N); -#else -template struct bitint {}; -template struct ubitint {}; -#endif // FMT_USE_BITINT - // __builtin_clz is broken in clang with Microsoft codegen: // https://github.com/fmtlib/fmt/issues/519. #if !FMT_MSC_VERSION @@ -4053,30 +4036,6 @@ template class formatter, Char> : public formatter, Char> {}; -template -struct formatter, Char> : formatter { - static_assert(N <= 64, "unsupported _BitInt"); - static auto format_as(detail::bitint x) -> long long { - return static_cast(x); - } - template - auto format(detail::bitint x, Context& ctx) const -> decltype(ctx.out()) { - return formatter::format(format_as(x), ctx); - } -}; - -template -struct formatter, Char> : formatter { - static_assert(N <= 64, "unsupported _BitInt"); - static auto format_as(detail::ubitint x) -> ullong { - return static_cast(x); - } - template - auto format(detail::ubitint x, Context& ctx) const -> decltype(ctx.out()) { - return formatter::format(format_as(x), ctx); - } -}; - template struct formatter : detail::native_formatter= 1500 && !defined(__CUDACC__) +# define FMT_USE_BITINT 1 +#else +# define FMT_USE_BITINT 0 +#endif + +#if FMT_USE_BITINT +FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension") +template using bitint = _BitInt(N); +template using ubitint = unsigned _BitInt(N); +#else +template struct bitint {}; +template struct ubitint {}; +#endif // FMT_USE_BITINT + #if FMT_CPP_LIB_FILESYSTEM template @@ -611,6 +628,30 @@ struct formatter< } }; +template +struct formatter, Char> : formatter { + static_assert(N <= 64, "unsupported _BitInt"); + static auto format_as(detail::bitint x) -> long long { + return static_cast(x); + } + template + auto format(detail::bitint x, Context& ctx) const -> decltype(ctx.out()) { + return formatter::format(format_as(x), ctx); + } +}; + +template +struct formatter, Char> : formatter { + static_assert(N <= 64, "unsupported _BitInt"); + static auto format_as(detail::ubitint x) -> ullong { + return static_cast(x); + } + template + auto format(detail::ubitint x, Context& ctx) const -> decltype(ctx.out()) { + return formatter::format(format_as(x), ctx); + } +}; + // We can't use std::vector::reference and // std::bitset::reference because the compiler can't deduce Allocator and N // in partial specialization. diff --git a/test/format-test.cc b/test/format-test.cc index 94c69f78..1d287377 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2612,42 +2612,6 @@ TEST(format_test, invalid_glibc_buffer) { } #endif // FMT_USE_FCNTL -#if FMT_USE_BITINT -FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension") - -TEST(format_test, bitint) { - using fmt::detail::bitint; - using fmt::detail::ubitint; - - EXPECT_EQ(fmt::format("{}", ubitint<3>(7)), "7"); - EXPECT_EQ(fmt::format("{}", bitint<7>()), "0"); - - EXPECT_EQ(fmt::format("{}", ubitint<15>(31000)), "31000"); - EXPECT_EQ(fmt::format("{}", bitint<16>(INT16_MIN)), "-32768"); - EXPECT_EQ(fmt::format("{}", bitint<16>(INT16_MAX)), "32767"); - - EXPECT_EQ(fmt::format("{}", ubitint<32>(4294967295)), "4294967295"); - - EXPECT_EQ(fmt::format("{}", ubitint<47>(140737488355327ULL)), - "140737488355327"); - EXPECT_EQ(fmt::format("{}", bitint<47>(-40737488355327LL)), - "-40737488355327"); - - // Check lvalues and const - auto a = bitint<8>(0); - auto b = ubitint<32>(4294967295); - const auto c = bitint<7>(0); - const auto d = ubitint<32>(4294967295); - EXPECT_EQ(fmt::format("{}", a), "0"); - EXPECT_EQ(fmt::format("{}", b), "4294967295"); - EXPECT_EQ(fmt::format("{}", c), "0"); - EXPECT_EQ(fmt::format("{}", d), "4294967295"); - - static_assert(fmt::is_formattable, char>{}, ""); - static_assert(fmt::is_formattable, char>{}, ""); -} -#endif - #ifdef __cpp_lib_byte TEST(base_test, format_byte) { auto s = std::string(); diff --git a/test/std-test.cc b/test/std-test.cc index c5a0c65a..b3ba57c3 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -403,6 +403,42 @@ TEST(std_test, type_info) { } #endif +#if FMT_USE_BITINT +FMT_PRAGMA_CLANG(diagnostic ignored "-Wbit-int-extension") + +TEST(std_test, bitint) { + using fmt::detail::bitint; + using fmt::detail::ubitint; + + EXPECT_EQ(fmt::format("{}", ubitint<3>(7)), "7"); + EXPECT_EQ(fmt::format("{}", bitint<7>()), "0"); + + EXPECT_EQ(fmt::format("{}", ubitint<15>(31000)), "31000"); + EXPECT_EQ(fmt::format("{}", bitint<16>(INT16_MIN)), "-32768"); + EXPECT_EQ(fmt::format("{}", bitint<16>(INT16_MAX)), "32767"); + + EXPECT_EQ(fmt::format("{}", ubitint<32>(4294967295)), "4294967295"); + + EXPECT_EQ(fmt::format("{}", ubitint<47>(140737488355327ULL)), + "140737488355327"); + EXPECT_EQ(fmt::format("{}", bitint<47>(-40737488355327LL)), + "-40737488355327"); + + // Check lvalues and const + auto a = bitint<8>(0); + auto b = ubitint<32>(4294967295); + const auto c = bitint<7>(0); + const auto d = ubitint<32>(4294967295); + EXPECT_EQ(fmt::format("{}", a), "0"); + EXPECT_EQ(fmt::format("{}", b), "4294967295"); + EXPECT_EQ(fmt::format("{}", c), "0"); + EXPECT_EQ(fmt::format("{}", d), "4294967295"); + + static_assert(fmt::is_formattable, char>{}, ""); + static_assert(fmt::is_formattable, char>{}, ""); +} +#endif + TEST(std_test, format_bit_reference) { std::bitset<2> bs(1); EXPECT_EQ(fmt::format("{} {}", bs[0], bs[1]), "true false");