Diagnose two silently violated template parameter requirements

Both were on the list of requirements that are not caught at compile time and
corrupt values rather than failing, and both are a plain size comparison:

- A BinaryType whose value_type is wider than one byte, which the readers and
  writers reinterpret as raw bytes anyway.
- A NumberUnsignedType too narrow to hold the absolute value of every
  NumberIntegerType value, which makes basic_json(INT64_MIN).dump() yield -0
  for std::int64_t with std::uint32_t.

Neither static_assert rejects a configuration that worked before: both only
fire where the result was already wrong. Also add the two comments the review
asked for, in write_bson_string() and calc_bson_array_size(), matching the
ones their counterparts already carry.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-08-31 19:52:26 +00:00
parent 626fdb098a
commit a4e09fa5b7
3 changed files with 34 additions and 0 deletions
@@ -1060,6 +1060,8 @@ class binary_writer
oa->write_characters(
reinterpret_cast<const CharType*>(value.data()),
value.size());
// the terminating null byte is written explicitly rather than taken
// from the buffer, so that string_t::data() need not be null-terminated
oa->write_character(to_char_type(0x00));
}
@@ -1151,6 +1153,9 @@ class binary_writer
const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
{
// the index is built as a std::string, while calc_bson_element_size
// takes a string_t; convert explicitly, as the two are only
// implicitly convertible for some string types
const auto key = std::to_string(array_index++);
return result + calc_bson_element_size(string_t(key.data(), key.size()), el);
});
+12
View File
@@ -403,6 +403,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @}
// Two template parameter requirements that would otherwise be silently
// violated: neither produces a diagnostic of its own, and both corrupt
// values rather than failing.
static_assert(sizeof(typename BinaryType::value_type) == 1,
"BinaryType::value_type must be exactly one byte wide, "
"because the binary readers and writers reinterpret the container's storage as raw bytes");
static_assert(sizeof(NumberUnsignedType) >= sizeof(NumberIntegerType),
"NumberUnsignedType must be at least as wide as NumberIntegerType, "
"because it has to hold the absolute value of every NumberIntegerType value");
private:
/// helper for exception-safe object creation