diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp index 42b6f1eb9..78e12af81 100644 --- a/include/nlohmann/detail/input/json_sax.hpp +++ b/include/nlohmann/detail/input/json_sax.hpp @@ -1301,13 +1301,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(v)); - ::new (static_cast(&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(v), std::is_nothrow_constructible < BasicJsonType, Value && > {}); } else { @@ -1316,6 +1312,25 @@ class json_sax_dom_parser : public json_sax_dom_error_state } } + /// a scalar cannot throw: construct it in place + template + JSON_HEDLEY_ALWAYS_INLINE + static void construct_member(BasicJsonType& member, Value&& v, std::true_type /*nothrow*/) + { + ::new (static_cast(&member)) BasicJsonType(std::forward(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 + JSON_HEDLEY_ALWAYS_INLINE + static void construct_member(BasicJsonType& member, Value&& v, std::false_type /*may throw*/) + { + BasicJsonType value(std::forward(v)); + ::new (static_cast(&member)) BasicJsonType(std::move(value)); + } + /// a custom base class may care about the lifetime of the value template static void set_member(BasicJsonType& member, Value&& v, std::false_type /*custom base*/) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0c48f765f..961feb9cd 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -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(v)); - ::new (static_cast(&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(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 + JSON_HEDLEY_ALWAYS_INLINE + static void construct_member(BasicJsonType& member, Value&& v, std::true_type /*nothrow*/) + { + ::new (static_cast(&member)) BasicJsonType(std::forward(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 + JSON_HEDLEY_ALWAYS_INLINE + static void construct_member(BasicJsonType& member, Value&& v, std::false_type /*may throw*/) + { + BasicJsonType value(std::forward(v)); + ::new (static_cast(&member)) BasicJsonType(std::move(value)); + } + /// a custom base class may care about the lifetime of the value template static void set_member(BasicJsonType& member, Value&& v, std::false_type /*custom base*/)