diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index ffa20d639..9d87d4f92 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -482,8 +482,27 @@ class json_pointer } /// @brief object member access with a key that is only copied if it is inserted + /// + /// Objects that can find the position of a key and insert there + /// (std::map) search once, others look the key up and add it if it is missing. template - static BasicJsonType& object_member(BasicJsonType& object, const string_t& key) + static auto object_member_impl(BasicJsonType& object, const string_t& key, detail::priority_tag<1> /*unused*/) + -> decltype(object.m_data.m_value.object->emplace_hint(object.m_data.m_value.object->lower_bound(key), key, nullptr), std::declval()) + { + auto& members = *object.m_data.m_value.object; + auto it = members.lower_bound(key); + if (it != members.end() && !members.key_comp()(key, it->first)) + { + return it->second; + } + + const auto old_capacity = object.container_capacity(); + it = members.emplace_hint(it, key, nullptr); + return object.set_parent_after_insert(it->second, old_capacity); + } + + template + static BasicJsonType& object_member_impl(BasicJsonType& object, const string_t& key, detail::priority_tag<0> /*unused*/) { auto& members = *object.m_data.m_value.object; const auto it = members.find(key); @@ -494,6 +513,12 @@ class json_pointer return object.operator[](key); } + template + static BasicJsonType& object_member(BasicJsonType& object, const string_t& key) + { + return object_member_impl(object, key, detail::priority_tag<1> {}); + } + JSON_PRIVATE_UNLESS_TESTED: json_pointer top() const { diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index b9bbe42e8..0fd6ebb1b 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -22832,8 +22832,27 @@ class json_pointer } /// @brief object member access with a key that is only copied if it is inserted + /// + /// Objects that can find the position of a key and insert there + /// (std::map) search once, others look the key up and add it if it is missing. template - static BasicJsonType& object_member(BasicJsonType& object, const string_t& key) + static auto object_member_impl(BasicJsonType& object, const string_t& key, detail::priority_tag<1> /*unused*/) + -> decltype(object.m_data.m_value.object->emplace_hint(object.m_data.m_value.object->lower_bound(key), key, nullptr), std::declval()) + { + auto& members = *object.m_data.m_value.object; + auto it = members.lower_bound(key); + if (it != members.end() && !members.key_comp()(key, it->first)) + { + return it->second; + } + + const auto old_capacity = object.container_capacity(); + it = members.emplace_hint(it, key, nullptr); + return object.set_parent_after_insert(it->second, old_capacity); + } + + template + static BasicJsonType& object_member_impl(BasicJsonType& object, const string_t& key, detail::priority_tag<0> /*unused*/) { auto& members = *object.m_data.m_value.object; const auto it = members.find(key); @@ -22844,6 +22863,12 @@ class json_pointer return object.operator[](key); } + template + static BasicJsonType& object_member(BasicJsonType& object, const string_t& key) + { + return object_member_impl(object, key, detail::priority_tag<1> {}); + } + JSON_PRIVATE_UNLESS_TESTED: json_pointer top() const {