Make comparisons with scalars noexcept only when the conversion is (#5751)
The comparison operators taking a scalar (==, !=, <, <=, >, >=, and C++20's <=>) convert the scalar to a basic_json and compare, but were unconditionally noexcept. When that conversion throws, the program called std::terminate instead of propagating the exception, e.g. when comparing a json with a string literal under memory pressure (std::bad_alloc) or with an enum value not mapped by NLOHMANN_JSON_SERIALIZE_ENUM_STRICT (out_of_range.410). clang-tidy 22.1 reports the latter as bugprone-exception-escape. Declare the 16 scalar overloads noexcept(std::is_nothrow_constructible<basic_json, ScalarType>::value): they stay noexcept for numbers, Booleans, nullptr, and plain enums, and are noexcept(false) for strings and enums whose to_json may throw. The comparisons of two basic_json values are unchanged. Restore the strict-enum comparisons removed from unit-conversions.cpp in the previous PR, check that comparing an unmapped strict enum now throws, and pin the new exception specifications in unit-noexcept.cpp. Document the exception safety of overload (2) on all seven operator pages. Ran make amalgamate. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 parent
63c10a51fc
commit
6d0867a85f
11 files changed
+125
-53
No files matched your search
@@ -5,17 +5,17 @@
|
||||
bool operator==(const_reference lhs, const_reference rhs) noexcept; // (1)
|
||||
|
||||
template<typename ScalarType>
|
||||
bool operator==(const_reference lhs, const ScalarType rhs) noexcept; // (2)
|
||||
bool operator==(const_reference lhs, const ScalarType rhs) noexcept(/* see below */); // (2)
|
||||
|
||||
template<typename ScalarType>
|
||||
bool operator==(ScalarType lhs, const const_reference rhs) noexcept; // (2)
|
||||
bool operator==(ScalarType lhs, const const_reference rhs) noexcept(/* see below */); // (2)
|
||||
|
||||
// since C++20
|
||||
class basic_json {
|
||||
bool operator==(const_reference rhs) const noexcept; // (1)
|
||||
|
||||
template<typename ScalarType>
|
||||
bool operator==(ScalarType rhs) const noexcept; // (2)
|
||||
bool operator==(ScalarType rhs) const noexcept(/* see below */); // (2)
|
||||
};
|
||||
```
|
||||
|
||||
@@ -46,7 +46,12 @@ whether the values `lhs`/`*this` and `rhs` are equal
|
||||
|
||||
## Exception safety
|
||||
|
||||
No-throw guarantee: this function never throws exceptions.
|
||||
1. No-throw guarantee: this function never throws exceptions.
|
||||
2. No-throw guarantee if converting the scalar to a JSON value cannot throw, as for numbers, Booleans, and
|
||||
`#!cpp nullptr`; the function is `#!cpp noexcept` exactly in that case. Otherwise, it throws what the conversion
|
||||
throws, for example `std::bad_alloc` when converting a string, or
|
||||
[`out_of_range.410`](../../home/exceptions.md#jsonexceptionout_of_range410) for an enum value not mapped by
|
||||
[`NLOHMANN_JSON_SERIALIZE_ENUM_STRICT`](../macros/nlohmann_json_serialize_enum_strict.md).
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -171,3 +176,4 @@ Linear.
|
||||
|
||||
1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0.
|
||||
2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0.
|
||||
Made conditionally `#!cpp noexcept` in version 3.13.0; before, a throwing conversion called `std::terminate`.
|
||||
Reference in new issue
Block a user