[gcc r17-3473] libstdc++: Format std::float16_t and std::bfloat16_t using respective std::to_chars overloads [PR126
Tomasz Kaminski via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:4b6ce501c4f1db06c8084170a68796622266b671 commit r17-3473-g4b6ce501c4f1db06c8084170a68796622266b671 Author: Tomasz Kamiński <[email protected]> Date: Thu Aug 13 09:51:56 2026 +0200 libstdc++: Format std::float16_t and std::bfloat16_t using respective std::to_chars overloads [PR126731] This patch removes the partial specialization for float16_t and bfloat16_t that formatted the values by casting to float. In consequence an implicit specialization of generic floating-point specialization is used, and to_chars overloads for their types are used. As explained in r13-3591-g0ae26533b3e268 (that adds corresponding to_chars overload), the shortest string (produced when no precision is specified) is shorter than float for above. As formatter specializations were defined under the same condition as corresponding to_chars overloads, the __formattable_float constrain on formatter floating-point specialization makes it enable in same cases. This reverted parts of r14-3305-g6cf214b4fc97f5 (revereted partially in r14-3329-g27d0cfcb2b33de), leading to (necessary for correctness) increase of the number template specializations. It also depends on preserving values of above types (instead of float) in basic_format_arg introduced r16-616-g9c9a7316adb996. The specializations for float32_t and float64_t are left unchanged, as their to_chars overloads are also implemented in terms of casting to float/double respectivelly. libstdc++-v3/ChangeLog: PR libstdc++/126731 * include/std/format (std::formatter<_Float16, _CharT>) (std::formatter<__format::__bflt16_t, _CharT>): Remove partial specializations. * testsuite/std/format/formatter/ext_float.cc: Test output for closest value to 1/10. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- libstdc++-v3/include/std/format | 44 ---------------------- .../testsuite/std/format/formatter/ext_float.cc | 22 ++++++----- 2 files changed, 13 insertions(+), 53 deletions(-) diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 729cb89ec600..8d530e883c35 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -3003,28 +3003,6 @@ namespace __format }; #endif -#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - // Reuse __formatter_fp<C>::format<float, Out> for _Float16. - template<__format::__char _CharT> - struct formatter<_Float16, _CharT> - { - formatter() = default; - - [[__gnu__::__always_inline__]] - constexpr typename basic_format_parse_context<_CharT>::iterator - parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f.parse(__pc); } - - template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(_Float16 __u, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f.format((float)__u, __fc); } - - private: - __format::__formatter_fp<_CharT> _M_f; - }; -#endif - #if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) // Reuse __formatter_fp<C>::format<float, Out> for _Float32. template<__format::__char _CharT> @@ -3114,28 +3092,6 @@ namespace __format }; #endif -#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - // Reuse __formatter_fp<C>::format<float, Out> for bfloat16_t. - template<__format::__char _CharT> - struct formatter<__format::__bflt16_t, _CharT> - { - formatter() = default; - - [[__gnu__::__always_inline__]] - constexpr typename basic_format_parse_context<_CharT>::iterator - parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f.parse(__pc); } - - template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(__gnu_cxx::__bfloat16_t __u, - basic_format_context<_Out, _CharT>& __fc) const - { return _M_f.format((float)__u, __fc); } - - private: - __format::__formatter_fp<_CharT> _M_f; - }; -#endif #endif // __cpp_lib_to_chars /** Format a pointer. diff --git a/libstdc++-v3/testsuite/std/format/formatter/ext_float.cc b/libstdc++-v3/testsuite/std/format/formatter/ext_float.cc index 82e696fa797c..7b231b070060 100644 --- a/libstdc++-v3/testsuite/std/format/formatter/ext_float.cc +++ b/libstdc++-v3/testsuite/std/format/formatter/ext_float.cc @@ -4,10 +4,14 @@ #include <testsuite_hooks.h> template<typename T> -bool format_float() +void +verify_output() { - auto s = std::format("{:#} != {:<+7.3f}", (T)-0.0, (T)0.5); - return s == "-0. != +0.500 "; + auto s = std::format("{:#} != {:<+7.3f}", T(-0.0), T(0.5)); + VERIFY( s == "-0. != +0.500 "); + + s = std::format("{}", T(1)/T(10)); + VERIFY( s == "0.1"); } #if __cplusplus > 202002L @@ -23,7 +27,7 @@ test_float16() { #if __FLT16_DIG__ if constexpr (formattable<_Float16>) - VERIFY( format_float<_Float16>() ); + verify_output<_Float16>(); else std::puts("Cannot format _Float16 on this target"); #endif @@ -34,7 +38,7 @@ test_float32() { #if __FLT32_DIG__ if constexpr (formattable<_Float32>) - VERIFY( format_float<_Float32>() ); + verify_output<_Float32>(); else std::puts("Cannot format _Float32 on this target"); #endif @@ -45,7 +49,7 @@ test_float64() { #if __FLT64_DIG__ if constexpr (formattable<_Float64>) - VERIFY( format_float<_Float64>() ); + verify_output<_Float64>(); else std::puts("Cannot format _Float64 on this target"); #endif @@ -56,13 +60,13 @@ test_float128() { #ifdef __SIZEOF_FLOAT128__ if constexpr (formattable<__float128>) - VERIFY( format_float<__float128>() ); + verify_output<__float128>(); else std::puts("Cannot format __float128 on this target"); #endif #if __FLT128_DIG__ if constexpr (formattable<_Float128>) - VERIFY( format_float<_Float128>() ); + verify_output<_Float128>(); else std::puts("Cannot format _Float128 on this target"); #endif @@ -75,7 +79,7 @@ test_bfloat16() using bfloat16_t = decltype(0.0bf16); if constexpr (formattable<bfloat16_t>) - VERIFY( format_float<bfloat16_t>() ); + verify_output<bfloat16_t>(); else std::puts("Cannot format bfloat16_t on this target"); #endif