From 71830be06d80b08a0a1eda8a34c063246c923792 Mon Sep 17 00:00:00 2001 From: chenguoping Date: Wed, 10 Jun 2020 19:27:28 +0800 Subject: [PATCH 1/6] fix issue#1275 --- include/nlohmann/json.hpp | 25 +++++++++++++++++++++++++ single_include/nlohmann/json.hpp | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index d1dc4119..0deb0583 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3788,6 +3788,31 @@ class basic_json JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); } + /*! + @brief overload for a default value of type rvalue + @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const + */ + template>::value + and not std::is_same::value, int>::type = 0> + detail::uncvref_t value(const typename object_t::key_type& key, ValueType && default_value) && + { + // only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if key is found, return value and given default value otherwise + const auto it = find(key); + if (it != end()) + { + return std::move(it->template get_ref()); + } + + return std::forward(default_value); + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); + } + /*! @brief overload for a default value of type const char* @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index dd9b21c4..9fd621c7 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -19566,6 +19566,31 @@ class basic_json JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); } + /*! + @brief overload for a default value of type rvalue + @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const + */ + template>::value + and not std::is_same::value, int>::type = 0> + detail::uncvref_t value(const typename object_t::key_type& key, ValueType && default_value) && + { + // only works for objects + if (JSON_HEDLEY_LIKELY(is_object())) + { + // if key is found, return value and given default value otherwise + const auto it = find(key); + if (it != end()) + { + return std::move(it->template get_ref()); + } + + return std::forward(default_value); + } + + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); + } + /*! @brief overload for a default value of type const char* @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const From a3df26b771cbe866e000615300302e2be22eb8a4 Mon Sep 17 00:00:00 2001 From: chenguoping Date: Wed, 10 Jun 2020 19:27:57 +0800 Subject: [PATCH 2/6] add some test cases --- test/src/unit-element_access2.cpp | 39 +++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index e881a947..6df0ca59 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -148,6 +148,45 @@ TEST_CASE("element access 2") SECTION("access specified element with default value") { + SECTION("move semantics") + { + SECTION("json is rvalue") + { + json j = {{"x", "123"}}; + std::string defval = "default"; + auto val = std::move(j).value("x", defval); + + CHECK(j["x"] == ""); + CHECK(defval == "default"); + CHECK(val == "123"); + } + + SECTION("default is rvalue") + { + json j = {{"x", "123"}}; + std::string defval = "default"; + auto val = std::move(j).value("y", std::move(defval)); + + CHECK(j["x"] == "123"); + CHECK(defval == ""); + CHECK(val == "default"); + } + + SECTION("access on non-object value") + { + json j_nonobject(json::value_t::array); + const json j_nonobject_const(j_nonobject); + std::string defval = "default"; + + CHECK_THROWS_AS(std::move(j_nonobject).value("foo", defval), json::type_error&); + CHECK_THROWS_AS(std::move(j_nonobject_const).value("foo", defval), json::type_error&); + CHECK_THROWS_WITH(std::move(j_nonobject).value("foo", defval), + "[json.exception.type_error.306] cannot use value() with array"); + CHECK_THROWS_WITH(std::move(j_nonobject_const).value("foo", defval), + "[json.exception.type_error.306] cannot use value() with array"); + } + } + SECTION("given a key") { SECTION("access existing value") From 8aaa4013a39786b57964741cd759539112c4fbf2 Mon Sep 17 00:00:00 2001 From: chenguoping Date: Wed, 17 Jun 2020 15:05:28 +0800 Subject: [PATCH 3/6] remove overload function, change default_value to rvalue --- include/nlohmann/json.hpp | 36 ++++++-------------------------- single_include/nlohmann/json.hpp | 36 ++++++-------------------------- 2 files changed, 12 insertions(+), 60 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 0deb0583..8f0347ea 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3770,7 +3770,7 @@ class basic_json template::value and not std::is_same::value, int>::type = 0> - ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const + ValueType value(const typename object_t::key_type& key, ValueType && default_value) const { // at only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -3782,36 +3782,12 @@ class basic_json return *it; } - return default_value; + return std::move(default_value); } JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); } - /*! - @brief overload for a default value of type rvalue - @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const - */ - template>::value - and not std::is_same::value, int>::type = 0> - detail::uncvref_t value(const typename object_t::key_type& key, ValueType && default_value) && - { - // only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if key is found, return value and given default value otherwise - const auto it = find(key); - if (it != end()) - { - return std::move(it->template get_ref()); - } - - return std::forward(default_value); - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); - } /*! @brief overload for a default value of type const char* @@ -3819,7 +3795,7 @@ class basic_json */ string_t value(const typename object_t::key_type& key, const char* default_value) const { - return value(key, string_t(default_value)); + return value(key, std::move(string_t(default_value))); } /*! @@ -3867,7 +3843,7 @@ class basic_json */ template::value, int>::type = 0> - ValueType value(const json_pointer& ptr, const ValueType& default_value) const + ValueType value(const json_pointer& ptr, ValueType && default_value) const { // at only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -3879,7 +3855,7 @@ class basic_json } JSON_INTERNAL_CATCH (out_of_range&) { - return default_value; + return std::move(default_value); } } @@ -3893,7 +3869,7 @@ class basic_json JSON_HEDLEY_NON_NULL(3) string_t value(const json_pointer& ptr, const char* default_value) const { - return value(ptr, string_t(default_value)); + return value(ptr, std::move(string_t(default_value))); } /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 9fd621c7..0c2cdf3d 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -19548,7 +19548,7 @@ class basic_json template::value and not std::is_same::value, int>::type = 0> - ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const + ValueType value(const typename object_t::key_type& key, ValueType && default_value) const { // at only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -19560,36 +19560,12 @@ class basic_json return *it; } - return default_value; + return std::move(default_value); } JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); } - /*! - @brief overload for a default value of type rvalue - @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const - */ - template>::value - and not std::is_same::value, int>::type = 0> - detail::uncvref_t value(const typename object_t::key_type& key, ValueType && default_value) && - { - // only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if key is found, return value and given default value otherwise - const auto it = find(key); - if (it != end()) - { - return std::move(it->template get_ref()); - } - - return std::forward(default_value); - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); - } /*! @brief overload for a default value of type const char* @@ -19597,7 +19573,7 @@ class basic_json */ string_t value(const typename object_t::key_type& key, const char* default_value) const { - return value(key, string_t(default_value)); + return value(key, std::move(string_t(default_value))); } /*! @@ -19645,7 +19621,7 @@ class basic_json */ template::value, int>::type = 0> - ValueType value(const json_pointer& ptr, const ValueType& default_value) const + ValueType value(const json_pointer& ptr, ValueType && default_value) const { // at only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -19657,7 +19633,7 @@ class basic_json } JSON_INTERNAL_CATCH (out_of_range&) { - return default_value; + return std::move(default_value); } } @@ -19671,7 +19647,7 @@ class basic_json JSON_HEDLEY_NON_NULL(3) string_t value(const json_pointer& ptr, const char* default_value) const { - return value(ptr, string_t(default_value)); + return value(ptr, std::move(string_t(default_value))); } /*! From f466919ec29fee46b1dbbb30d241d80b2334cdfe Mon Sep 17 00:00:00 2001 From: chenguoping Date: Wed, 17 Jun 2020 15:07:25 +0800 Subject: [PATCH 4/6] change test cases --- test/src/unit-element_access2.cpp | 41 ++----------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index 6df0ca59..d2a19108 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -148,45 +148,6 @@ TEST_CASE("element access 2") SECTION("access specified element with default value") { - SECTION("move semantics") - { - SECTION("json is rvalue") - { - json j = {{"x", "123"}}; - std::string defval = "default"; - auto val = std::move(j).value("x", defval); - - CHECK(j["x"] == ""); - CHECK(defval == "default"); - CHECK(val == "123"); - } - - SECTION("default is rvalue") - { - json j = {{"x", "123"}}; - std::string defval = "default"; - auto val = std::move(j).value("y", std::move(defval)); - - CHECK(j["x"] == "123"); - CHECK(defval == ""); - CHECK(val == "default"); - } - - SECTION("access on non-object value") - { - json j_nonobject(json::value_t::array); - const json j_nonobject_const(j_nonobject); - std::string defval = "default"; - - CHECK_THROWS_AS(std::move(j_nonobject).value("foo", defval), json::type_error&); - CHECK_THROWS_AS(std::move(j_nonobject_const).value("foo", defval), json::type_error&); - CHECK_THROWS_WITH(std::move(j_nonobject).value("foo", defval), - "[json.exception.type_error.306] cannot use value() with array"); - CHECK_THROWS_WITH(std::move(j_nonobject_const).value("foo", defval), - "[json.exception.type_error.306] cannot use value() with array"); - } - } - SECTION("given a key") { SECTION("access existing value") @@ -226,6 +187,7 @@ TEST_CASE("element access 2") CHECK(j.value("_", 12.34) == Approx(12.34)); CHECK(j.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); CHECK(j.value("_", json({10, 100})) == json({10, 100})); + CHECK(j.value("_", std::move("default_value")) == "default_value"); CHECK(j_const.value("_", 2) == 2); CHECK(j_const.value("_", 2u) == 2u); @@ -234,6 +196,7 @@ TEST_CASE("element access 2") CHECK(j_const.value("_", 12.34) == Approx(12.34)); CHECK(j_const.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); CHECK(j_const.value("_", json({10, 100})) == json({10, 100})); + CHECK(j_const.value("_", std::move("default_value")) == "default_value"); } SECTION("access on non-object type") From da8fa3535a71515aeddc68421e63017c1f503d3a Mon Sep 17 00:00:00 2001 From: chenguoping Date: Wed, 17 Jun 2020 20:41:31 +0800 Subject: [PATCH 5/6] drop testcase --- test/src/unit-element_access2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp index d2a19108..e881a947 100644 --- a/test/src/unit-element_access2.cpp +++ b/test/src/unit-element_access2.cpp @@ -187,7 +187,6 @@ TEST_CASE("element access 2") CHECK(j.value("_", 12.34) == Approx(12.34)); CHECK(j.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); CHECK(j.value("_", json({10, 100})) == json({10, 100})); - CHECK(j.value("_", std::move("default_value")) == "default_value"); CHECK(j_const.value("_", 2) == 2); CHECK(j_const.value("_", 2u) == 2u); @@ -196,7 +195,6 @@ TEST_CASE("element access 2") CHECK(j_const.value("_", 12.34) == Approx(12.34)); CHECK(j_const.value("_", json({{"foo", "bar"}})) == json({{"foo", "bar"}})); CHECK(j_const.value("_", json({10, 100})) == json({10, 100})); - CHECK(j_const.value("_", std::move("default_value")) == "default_value"); } SECTION("access on non-object type") From 4a6c68c7eba1c6c84e90c238b3e1f27dcb096d38 Mon Sep 17 00:00:00 2001 From: chenguoping Date: Wed, 17 Jun 2020 20:44:31 +0800 Subject: [PATCH 6/6] drop new blank line --- include/nlohmann/json.hpp | 1 - single_include/nlohmann/json.hpp | 1 - 2 files changed, 2 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 8f0347ea..990fe3cf 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -3788,7 +3788,6 @@ class basic_json JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); } - /*! @brief overload for a default value of type const char* @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0c2cdf3d..8a79c479 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -19566,7 +19566,6 @@ class basic_json JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); } - /*! @brief overload for a default value of type const char* @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const