From edd18d071eede5d706d5a4136707725e377bced7 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 30 Sep 2026 18:18:42 +0200 Subject: [PATCH] Unify float marker selection and fix the long double compile error Four formats picked between a float32 and float64 marker through four different helper styles: dummy-argument overloads for CBOR and MessagePack, an std::is_same template for BON8, and a runtime if-chain on input_format_t for write_compact_float(). With number_float_t set to long double, to_cbor, to_msgpack and to_ubjson failed inside the library with "call to 'get_cbor_float_prefix' is ambiguous", while to_bson kept working because write_bson_double() takes a plain double. Change write_compact_float() to take the two marker bytes directly (each of its three callers already knows them at compile time) instead of an input_format_t it only forwarded, and delete the now-unused get_cbor_float_prefix(), get_msgpack_float_prefix(), get_bon8_float_prefix() and get_compact_float_prefix() helpers. Turn the two get_ubjson_float_prefix() overloads into one template. Both write_compact_float() and get_ubjson_float_prefix() now report an unsupported number_float_t with a static_assert naming the requirement, rather than an ambiguous-overload error; the assert lives in the function body, not the class scope, so to_bson with long double is unaffected. Verified with a probe basic_json<..., long double>: to_bson still compiles and round-trips, while to_cbor/to_msgpack/to_ubjson now fail to compile with the new static_assert message. This changes the text of an existing compile error for users with an unsupported number_float_t (documented as a public-API-visible change in #5710). #5710 item 1 Signed-off-by: Niels Lohmann --- .../nlohmann/detail/output/binary_writer.hpp | 83 ++++++------------- single_include/nlohmann/json.hpp | 83 ++++++------------- 2 files changed, 48 insertions(+), 118 deletions(-) diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index ac3832a11..9bbfb5c71 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -204,7 +204,7 @@ class binary_writer } else { - write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); + write_compact_float(j.m_data.m_value.number_float, to_char_type(0xFA), to_char_type(0xFB)); } break; } @@ -428,7 +428,7 @@ class binary_writer case value_t::number_float: { - write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); + write_compact_float(j.m_data.m_value.number_float, to_char_type(0xCA), to_char_type(0xCB)); break; } @@ -1410,52 +1410,6 @@ class binary_writer } } - static constexpr CharType get_cbor_float_prefix(float /*unused*/) - { - return to_char_type(0xFA); // Single-Precision Float - } - - static constexpr CharType get_cbor_float_prefix(double /*unused*/) - { - return to_char_type(0xFB); // Double-Precision Float - } - - ///////////// - // MsgPack // - ///////////// - - static constexpr CharType get_msgpack_float_prefix(float /*unused*/) - { - return to_char_type(0xCA); // float 32 - } - - static constexpr CharType get_msgpack_float_prefix(double /*unused*/) - { - return to_char_type(0xCB); // float 64 - } - - /// @return the BON8 type marker for binary32 (float) or binary64 (double) - template - static constexpr CharType get_bon8_float_prefix() - { - return to_char_type(std::is_same::value ? 0x8E : 0x8F); - } - - /// @return the type marker for a FloatType value in @a format (CBOR, MessagePack, or BON8) - template - static CharType get_compact_float_prefix(const detail::input_format_t format) - { - if (format == detail::input_format_t::cbor) - { - return get_cbor_float_prefix(FloatType{}); - } - if (format == detail::input_format_t::bon8) - { - return get_bon8_float_prefix(); - } - return get_msgpack_float_prefix(FloatType{}); - } - //////////// // UBJSON // //////////// @@ -1645,14 +1599,16 @@ class binary_writer || marker == 'T' || marker == 'F' || marker == 'N' || marker == 'Z'; } - static constexpr CharType get_ubjson_float_prefix(float /*unused*/) + /// @return the UBJSON/BJData type marker for a float or double value + /// + /// number_float_t must be float or double; a static_assert (rather than + /// an ambiguous overload) reports an unsupported number_float_t clearly. + template + static constexpr CharType get_ubjson_float_prefix(FloatType /*unused*/) { - return 'd'; // float 32 - } - - static constexpr CharType get_ubjson_float_prefix(double /*unused*/) - { - return 'D'; // float 64 + static_assert(std::is_same::value || std::is_same::value, + "number_float_t must be float or double for the UBJSON/BJData writer"); + return std::is_same::value ? 'd' : 'D'; // float 32 / float 64 } /*! @@ -2240,7 +2196,7 @@ class binary_writer } else { - write_compact_float(n, detail::input_format_t::bon8); + write_compact_float(n, to_char_type(0x8E), to_char_type(0x8F)); } #ifdef __GNUC__ JSON_HEDLEY_DIAGNOSTIC_POP @@ -2362,8 +2318,17 @@ class binary_writer oa.write_characters(vec.data(), sizeof(NumberType)); } - void write_compact_float(const number_float_t n, detail::input_format_t format) + /// @brief write @a n using @a float32_marker if it round-trips through + /// float, otherwise using @a float64_marker + /// + /// @a float32_marker and @a float64_marker are the format-specific type + /// markers (CBOR: 0xFA/0xFB, MessagePack: 0xCA/0xCB, BON8: 0x8E/0x8F); + /// each caller already knows them at compile time, so the format itself + /// no longer needs to be passed in. + void write_compact_float(const number_float_t n, const CharType float32_marker, const CharType float64_marker) { + static_assert(std::is_same::value || std::is_same::value, + "number_float_t must be float or double for the CBOR/MessagePack/BON8 writer"); #ifdef __GNUC__ JSON_HEDLEY_DIAGNOSTIC_PUSH JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal") @@ -2381,12 +2346,12 @@ class binary_writer static_cast(n) <= static_cast((std::numeric_limits::max)()) && static_cast(static_cast(n)) == static_cast(n)))) { - oa.write_character(get_compact_float_prefix(format)); + oa.write_character(float32_marker); write_number(static_cast(n)); } else { - oa.write_character(get_compact_float_prefix(format)); + oa.write_character(float64_marker); write_number(n); } #ifdef __GNUC__ diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index cc542156c..147bf8b52 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -20497,7 +20497,7 @@ class binary_writer } else { - write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); + write_compact_float(j.m_data.m_value.number_float, to_char_type(0xFA), to_char_type(0xFB)); } break; } @@ -20721,7 +20721,7 @@ class binary_writer case value_t::number_float: { - write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); + write_compact_float(j.m_data.m_value.number_float, to_char_type(0xCA), to_char_type(0xCB)); break; } @@ -21703,52 +21703,6 @@ class binary_writer } } - static constexpr CharType get_cbor_float_prefix(float /*unused*/) - { - return to_char_type(0xFA); // Single-Precision Float - } - - static constexpr CharType get_cbor_float_prefix(double /*unused*/) - { - return to_char_type(0xFB); // Double-Precision Float - } - - ///////////// - // MsgPack // - ///////////// - - static constexpr CharType get_msgpack_float_prefix(float /*unused*/) - { - return to_char_type(0xCA); // float 32 - } - - static constexpr CharType get_msgpack_float_prefix(double /*unused*/) - { - return to_char_type(0xCB); // float 64 - } - - /// @return the BON8 type marker for binary32 (float) or binary64 (double) - template - static constexpr CharType get_bon8_float_prefix() - { - return to_char_type(std::is_same::value ? 0x8E : 0x8F); - } - - /// @return the type marker for a FloatType value in @a format (CBOR, MessagePack, or BON8) - template - static CharType get_compact_float_prefix(const detail::input_format_t format) - { - if (format == detail::input_format_t::cbor) - { - return get_cbor_float_prefix(FloatType{}); - } - if (format == detail::input_format_t::bon8) - { - return get_bon8_float_prefix(); - } - return get_msgpack_float_prefix(FloatType{}); - } - //////////// // UBJSON // //////////// @@ -21938,14 +21892,16 @@ class binary_writer || marker == 'T' || marker == 'F' || marker == 'N' || marker == 'Z'; } - static constexpr CharType get_ubjson_float_prefix(float /*unused*/) + /// @return the UBJSON/BJData type marker for a float or double value + /// + /// number_float_t must be float or double; a static_assert (rather than + /// an ambiguous overload) reports an unsupported number_float_t clearly. + template + static constexpr CharType get_ubjson_float_prefix(FloatType /*unused*/) { - return 'd'; // float 32 - } - - static constexpr CharType get_ubjson_float_prefix(double /*unused*/) - { - return 'D'; // float 64 + static_assert(std::is_same::value || std::is_same::value, + "number_float_t must be float or double for the UBJSON/BJData writer"); + return std::is_same::value ? 'd' : 'D'; // float 32 / float 64 } /*! @@ -22533,7 +22489,7 @@ class binary_writer } else { - write_compact_float(n, detail::input_format_t::bon8); + write_compact_float(n, to_char_type(0x8E), to_char_type(0x8F)); } #ifdef __GNUC__ JSON_HEDLEY_DIAGNOSTIC_POP @@ -22655,8 +22611,17 @@ class binary_writer oa.write_characters(vec.data(), sizeof(NumberType)); } - void write_compact_float(const number_float_t n, detail::input_format_t format) + /// @brief write @a n using @a float32_marker if it round-trips through + /// float, otherwise using @a float64_marker + /// + /// @a float32_marker and @a float64_marker are the format-specific type + /// markers (CBOR: 0xFA/0xFB, MessagePack: 0xCA/0xCB, BON8: 0x8E/0x8F); + /// each caller already knows them at compile time, so the format itself + /// no longer needs to be passed in. + void write_compact_float(const number_float_t n, const CharType float32_marker, const CharType float64_marker) { + static_assert(std::is_same::value || std::is_same::value, + "number_float_t must be float or double for the CBOR/MessagePack/BON8 writer"); #ifdef __GNUC__ JSON_HEDLEY_DIAGNOSTIC_PUSH JSON_HEDLEY_PRAGMA(GCC diagnostic ignored "-Wfloat-equal") @@ -22674,12 +22639,12 @@ class binary_writer static_cast(n) <= static_cast((std::numeric_limits::max)()) && static_cast(static_cast(n)) == static_cast(n)))) { - oa.write_character(get_compact_float_prefix(format)); + oa.write_character(float32_marker); write_number(static_cast(n)); } else { - oa.write_character(get_compact_float_prefix(format)); + oa.write_character(float64_marker); write_number(n); } #ifdef __GNUC__