Add formatting support for <stdfloat> types

Provide format_as for std::float16_t and std::bfloat16_t and dedicated
std::complex formatters so fmt::print works with C++23 stdfloat types
(fixes #4725).
This commit is contained in:
wuyangfan 2026-05-17 23:15:39 +08:00
parent 2f18a88e68
commit 1b8b08589e
3 changed files with 62 additions and 0 deletions

View File

@ -514,6 +514,9 @@ chrono-format-specifications).
https://en.cppreference.com/w/cpp/utility/source_location)
- [`std::thread::id`](https://en.cppreference.com/w/cpp/thread/thread/id)
- [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant/variant)
- C++23 [`std::float16_t`](https://en.cppreference.com/w/cpp/types/float16_t) /
[`std::bfloat16_t`](https://en.cppreference.com/w/cpp/types/bfloat16_t) and
`std::complex` of those types (via `format_as`, when `<stdfloat>` is available)
::: ptr(const std::unique_ptr<T, Deleter>&)

View File

@ -804,6 +804,55 @@ struct formatter<std::reference_wrapper<T>, Char,
}
};
#if FMT_HAS_INCLUDE(<stdfloat>) && defined(__cpp_lib_stdfloat)
# include <stdfloat>
inline auto format_as(std::float16_t value) -> float {
return static_cast<float>(value);
}
inline auto format_as(std::bfloat16_t value) -> float {
return static_cast<float>(value);
}
template <typename Char>
struct formatter<std::complex<std::float16_t>, Char> {
private:
formatter<std::complex<float>, Char> underlying_;
public:
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
return underlying_.parse(ctx);
}
template <typename FormatContext>
auto format(const std::complex<std::float16_t>& value, FormatContext& ctx) const
-> decltype(ctx.out()) {
return underlying_.format(
std::complex<float>(static_cast<float>(value.real()),
static_cast<float>(value.imag())),
ctx);
}
};
template <typename Char>
struct formatter<std::complex<std::bfloat16_t>, Char> {
private:
formatter<std::complex<float>, Char> underlying_;
public:
FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
return underlying_.parse(ctx);
}
template <typename FormatContext>
auto format(const std::complex<std::bfloat16_t>& value,
FormatContext& ctx) const -> decltype(ctx.out()) {
return underlying_.format(
std::complex<float>(static_cast<float>(value.real()),
static_cast<float>(value.imag())),
ctx);
}
};
#endif // stdfloat
FMT_END_NAMESPACE
#endif // FMT_STD_H_

View File

@ -111,6 +111,16 @@ TEST(std_test, complex) {
"(1.00-2.20i) ");
}
#if FMT_HAS_INCLUDE(<stdfloat>) && defined(__cpp_lib_stdfloat)
# include <stdfloat>
TEST(std_test, stdfloat) {
std::float16_t f16 = std::float16_t(1.5f);
EXPECT_EQ(fmt::format("{}", f16), fmt::format("{}", 1.5f));
EXPECT_EQ(fmt::format("{}", std::complex<std::float16_t>(f16, std::float16_t(2.f))),
fmt::format("{}", std::complex<float>(1.5f, 2.f)));
}
#endif
#ifdef __cpp_lib_source_location
TEST(std_test, source_location) {
std::source_location loc = std::source_location::current();