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:
2 files changed
+44
-14
No files matched your search
@@ -1301,13 +1301,9 @@ class json_sax_dom_parser : public json_sax_dom_error_state
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_LIKELY(member.is_null()))
|
if (JSON_HEDLEY_LIKELY(member.is_null()))
|
||||||
{
|
{
|
||||||
// a new member is null and holds nothing: move the value over it
|
// a new member is null and holds nothing: construct the value
|
||||||
// instead of destroying and swapping. The value is created first,
|
// over it instead of destroying and swapping
|
||||||
// because creating a container or a string can throw, and a
|
construct_member(member, std::forward<Value>(v), std::is_nothrow_constructible < BasicJsonType, Value && > {});
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
else
|
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<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
|
/// a custom base class may care about the lifetime of the value
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
static void set_member(BasicJsonType& member, Value&& v, std::false_type /*custom base*/)
|
static void set_member(BasicJsonType& member, Value&& v, std::false_type /*custom base*/)
|
||||||
|
|||||||
Generated
+22
-7
@@ -16946,13 +16946,9 @@ class json_sax_dom_parser : public json_sax_dom_error_state
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_LIKELY(member.is_null()))
|
if (JSON_HEDLEY_LIKELY(member.is_null()))
|
||||||
{
|
{
|
||||||
// a new member is null and holds nothing: move the value over it
|
// a new member is null and holds nothing: construct the value
|
||||||
// instead of destroying and swapping. The value is created first,
|
// over it instead of destroying and swapping
|
||||||
// because creating a container or a string can throw, and a
|
construct_member(member, std::forward<Value>(v), std::is_nothrow_constructible < BasicJsonType, Value && > {});
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
else
|
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
|
/// a custom base class may care about the lifetime of the value
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
static void set_member(BasicJsonType& member, Value&& v, std::false_type /*custom base*/)
|
static void set_member(BasicJsonType& member, Value&& v, std::false_type /*custom base*/)
|
||||||
|
|||||||
Reference in new issue
Block a user