Move _BitInt next to bitref formatter

This commit is contained in:
Victor Zverovich 2026-02-02 16:34:12 -08:00
parent 27b7be63bf
commit 3f98b54bd7
4 changed files with 77 additions and 77 deletions

View File

@ -196,23 +196,6 @@ struct is_contiguous<std::basic_string<Char, Traits, Allocator>>
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 <int N> using bitint = _BitInt(N);
template <int N> using ubitint = unsigned _BitInt(N);
#else
template <int N> struct bitint {};
template <int N> 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 <typename Char, typename Traits, typename Allocator>
class formatter<std::basic_string<Char, Traits, Allocator>, Char>
: public formatter<basic_string_view<Char>, Char> {};
template <int N, typename Char>
struct formatter<detail::bitint<N>, Char> : formatter<long long, Char> {
static_assert(N <= 64, "unsupported _BitInt");
static auto format_as(detail::bitint<N> x) -> long long {
return static_cast<long long>(x);
}
template <typename Context>
auto format(detail::bitint<N> x, Context& ctx) const -> decltype(ctx.out()) {
return formatter<long long, Char>::format(format_as(x), ctx);
}
};
template <int N, typename Char>
struct formatter<detail::ubitint<N>, Char> : formatter<ullong, Char> {
static_assert(N <= 64, "unsupported _BitInt");
static auto format_as(detail::ubitint<N> x) -> ullong {
return static_cast<ullong>(x);
}
template <typename Context>
auto format(detail::ubitint<N> x, Context& ctx) const -> decltype(ctx.out()) {
return formatter<ullong, Char>::format(format_as(x), ctx);
}
};
template <typename Char>
struct formatter<detail::float128, Char>
: detail::native_formatter<detail::float128, Char,

View File

@ -79,6 +79,23 @@
FMT_BEGIN_NAMESPACE
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 <int N> using bitint = _BitInt(N);
template <int N> using ubitint = unsigned _BitInt(N);
#else
template <int N> struct bitint {};
template <int N> struct ubitint {};
#endif // FMT_USE_BITINT
#if FMT_CPP_LIB_FILESYSTEM
template <typename Char, typename PathChar>
@ -611,6 +628,30 @@ struct formatter<
}
};
template <int N, typename Char>
struct formatter<detail::bitint<N>, Char> : formatter<long long, Char> {
static_assert(N <= 64, "unsupported _BitInt");
static auto format_as(detail::bitint<N> x) -> long long {
return static_cast<long long>(x);
}
template <typename Context>
auto format(detail::bitint<N> x, Context& ctx) const -> decltype(ctx.out()) {
return formatter<long long, Char>::format(format_as(x), ctx);
}
};
template <int N, typename Char>
struct formatter<detail::ubitint<N>, Char> : formatter<ullong, Char> {
static_assert(N <= 64, "unsupported _BitInt");
static auto format_as(detail::ubitint<N> x) -> ullong {
return static_cast<ullong>(x);
}
template <typename Context>
auto format(detail::ubitint<N> x, Context& ctx) const -> decltype(ctx.out()) {
return formatter<ullong, Char>::format(format_as(x), ctx);
}
};
// We can't use std::vector<bool, Allocator>::reference and
// std::bitset<N>::reference because the compiler can't deduce Allocator and N
// in partial specialization.

View File

@ -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<bitint<64>, char>{}, "");
static_assert(fmt::is_formattable<ubitint<64>, char>{}, "");
}
#endif
#ifdef __cpp_lib_byte
TEST(base_test, format_byte) {
auto s = std::string();

View File

@ -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<bitint<64>, char>{}, "");
static_assert(fmt::is_formattable<ubitint<64>, char>{}, "");
}
#endif
TEST(std_test, format_bit_reference) {
std::bitset<2> bs(1);
EXPECT_EQ(fmt::format("{} {}", bs[0], bs[1]), "true false");