From 71830be06d80b08a0a1eda8a34c063246c923792 Mon Sep 17 00:00:00 2001
From: chenguoping <chenguopingdota@163.com>
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<class ValueType, typename std::enable_if<
+                 std::is_convertible<basic_json_t, detail::uncvref_t<ValueType>>::value
+                 and not std::is_same<value_t, ValueType>::value, int>::type = 0>
+    detail::uncvref_t<ValueType> 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<ValueType&>());
+            }
+
+            return std::forward<ValueType>(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<class ValueType, typename std::enable_if<
+                 std::is_convertible<basic_json_t, detail::uncvref_t<ValueType>>::value
+                 and not std::is_same<value_t, ValueType>::value, int>::type = 0>
+    detail::uncvref_t<ValueType> 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<ValueType&>());
+            }
+
+            return std::forward<ValueType>(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 <chenguopingdota@163.com>
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 <chenguopingdota@163.com>
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<class ValueType, typename std::enable_if<
                  std::is_convertible<basic_json_t, ValueType>::value
                  and not std::is_same<value_t, ValueType>::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<class ValueType, typename std::enable_if<
-                 std::is_convertible<basic_json_t, detail::uncvref_t<ValueType>>::value
-                 and not std::is_same<value_t, ValueType>::value, int>::type = 0>
-    detail::uncvref_t<ValueType> 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<ValueType&>());
-            }
-
-            return std::forward<ValueType>(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<class ValueType, typename std::enable_if<
                  std::is_convertible<basic_json_t, ValueType>::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<class ValueType, typename std::enable_if<
                  std::is_convertible<basic_json_t, ValueType>::value
                  and not std::is_same<value_t, ValueType>::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<class ValueType, typename std::enable_if<
-                 std::is_convertible<basic_json_t, detail::uncvref_t<ValueType>>::value
-                 and not std::is_same<value_t, ValueType>::value, int>::type = 0>
-    detail::uncvref_t<ValueType> 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<ValueType&>());
-            }
-
-            return std::forward<ValueType>(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<class ValueType, typename std::enable_if<
                  std::is_convertible<basic_json_t, ValueType>::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 <chenguopingdota@163.com>
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 <chenguopingdota@163.com>
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 <chenguopingdota@163.com>
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