Construct a scalar member in place; only a throwing value goes through a temporary

Creating the value first and moving it over the member is needed only when
creating it can throw (a string, a binary value or a container). A scalar
or null is again constructed in place, without the extra move and destroy
per member (and, with JSON_DIAGNOSTICS, without the extra set_parents()).

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-11-02 09:37:36 +01:00
1 parent 8aff27a0f9
commit 4809610d60
2 files changed
+44 -14

No files matched your search

+22 -7
View File
@@ -16946,13 +16946,9 @@ class json_sax_dom_parser : public json_sax_dom_error_state
{
if (JSON_HEDLEY_LIKELY(member.is_null()))
{
// a new member is null and holds nothing: move the value over it
// instead of destroying and swapping. The value is created first,
// because creating a container or a string can throw, and a
// constructor that was interrupted must not have touched the
// member (#5985); the move constructor is noexcept
BasicJsonType value(std::forward<Value>(v));
::new (static_cast<void*>(&member)) BasicJsonType(std::move(value));
// a new member is null and holds nothing: construct the value
// over it instead of destroying and swapping
construct_member(member, std::forward<Value>(v), std::is_nothrow_constructible < BasicJsonType, Value && > {});
}
else
{
@@ -16961,6 +16957,25 @@ class json_sax_dom_parser : public json_sax_dom_error_state
}
}
/// a scalar cannot throw: construct it in place
template<typename Value>
JSON_HEDLEY_ALWAYS_INLINE
static void construct_member(BasicJsonType& member, Value&& v, std::true_type /*nothrow*/)
{
::new (static_cast<void*>(&member)) BasicJsonType(std::forward<Value>(v));
}
/// creating a container or a string can throw, and a constructor that was
/// interrupted must not have touched the member (#5985): create the value
/// first, then move it over the member (the move constructor is noexcept)
template<typename Value>
JSON_HEDLEY_ALWAYS_INLINE
static void construct_member(BasicJsonType& member, Value&& v, std::false_type /*may throw*/)
{
BasicJsonType value(std::forward<Value>(v));
::new (static_cast<void*>(&member)) BasicJsonType(std::move(value));
}
/// a custom base class may care about the lifetime of the value
template<typename Value>
static void set_member(BasicJsonType& member, Value&& v, std::false_type /*custom base*/)