From 8d8f8907715798dcca106509e4d9056a2b9f784e Mon Sep 17 00:00:00 2001
From: Niels Lohmann <mail@nlohmann.me>
Date: Tue, 10 Apr 2018 08:29:07 +0200
Subject: [PATCH 1/2] :hankey: first try on #1045

---
 .../detail/iterators/iteration_proxy.hpp      | 17 +++++++++++++++
 single_include/nlohmann/json.hpp              | 17 +++++++++++++++
 test/src/unit-regression.cpp                  | 21 +++++++++++++++++++
 3 files changed, 55 insertions(+)

diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp
index 7547d038..b035a812 100644
--- a/include/nlohmann/detail/iterators/iteration_proxy.hpp
+++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp
@@ -2,6 +2,7 @@
 
 #include <cstddef> // size_t
 #include <string> // string, to_string
+#include <iterator> // input_iterator_tag
 
 #include <nlohmann/detail/value_t.hpp>
 
@@ -16,6 +17,13 @@ template<typename IteratorType> class iteration_proxy
     /// helper class for iteration
     class iteration_proxy_internal
     {
+      public:
+        using difference_type = std::ptrdiff_t;
+        using value_type = iteration_proxy_internal;
+        using pointer = iteration_proxy_internal*;
+        using reference = iteration_proxy_internal&;
+        using iterator_category = std::input_iterator_tag;
+
       private:
         /// the iterator
         IteratorType anchor;
@@ -25,6 +33,9 @@ template<typename IteratorType> class iteration_proxy
       public:
         explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
 
+        iteration_proxy_internal(const iteration_proxy_internal&) = default;
+        iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
+
         /// dereference operator (needed for range-based for)
         iteration_proxy_internal& operator*()
         {
@@ -40,6 +51,12 @@ template<typename IteratorType> class iteration_proxy
             return *this;
         }
 
+        /// equality operator (needed for InputIterator)
+        bool operator==(const iteration_proxy_internal& o) const noexcept
+        {
+            return anchor == o.anchor;
+        }
+
         /// inequality operator (needed for range-based for)
         bool operator!=(const iteration_proxy_internal& o) const noexcept
         {
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index b7558aa5..ce534f34 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -4491,6 +4491,7 @@ class iter_impl
 
 #include <cstddef> // size_t
 #include <string> // string, to_string
+#include <iterator> // input_iterator_tag
 
 // #include <nlohmann/detail/value_t.hpp>
 
@@ -4506,6 +4507,13 @@ template<typename IteratorType> class iteration_proxy
     /// helper class for iteration
     class iteration_proxy_internal
     {
+      public:
+        using difference_type = std::ptrdiff_t;
+        using value_type = iteration_proxy_internal;
+        using pointer = iteration_proxy_internal*;
+        using reference = iteration_proxy_internal&;
+        using iterator_category = std::input_iterator_tag;
+
       private:
         /// the iterator
         IteratorType anchor;
@@ -4515,6 +4523,9 @@ template<typename IteratorType> class iteration_proxy
       public:
         explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
 
+        iteration_proxy_internal(const iteration_proxy_internal&) = default;
+        iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
+
         /// dereference operator (needed for range-based for)
         iteration_proxy_internal& operator*()
         {
@@ -4530,6 +4541,12 @@ template<typename IteratorType> class iteration_proxy
             return *this;
         }
 
+        /// equality operator (needed for InputIterator)
+        bool operator==(const iteration_proxy_internal& o) const noexcept
+        {
+            return anchor == o.anchor;
+        }
+
         /// inequality operator (needed for range-based for)
         bool operator!=(const iteration_proxy_internal& o) const noexcept
         {
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index 01e68957..d26e0e57 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -1615,4 +1615,25 @@ TEST_CASE("regression tests")
         float_json j2 = {1000.0, 2000.0, 3000.0};
         CHECK(float_json::from_ubjson(float_json::to_ubjson(j2, true, true)) == j2);
     }
+
+    SECTION("issue #1045 - Using STL algorithms with JSON containers with expected results?")
+    {
+        json diffs = nlohmann::json::array();
+        json m1{{"key1", 42}};
+        json m2{{"key2", 42}};
+        auto p1 = m1.items();
+        auto p2 = m2.items();
+
+        using it_type = decltype(p1.begin());
+
+        std::set_difference(
+            p1.begin(), p1.end(),
+            p2.begin(), p2.end(),
+            std::inserter(diffs, diffs.end()), [&](const it_type & e1, const it_type & e2) -> bool
+        {
+            return (e1.key() < e2.key()) and (e1.value() < e2.value());
+        });
+
+        CHECK(diffs.size() == 2);
+    }
 }

From 1566ad40535a38b27f03ab53ef95a6308436f96e Mon Sep 17 00:00:00 2001
From: Danielc <daniel.cohen599@gmail.com>
Date: Sat, 16 Jun 2018 12:01:49 +0300
Subject: [PATCH 2/2] fixed compile error for #1045; to_json for
 iternation_proxy_internal was needed

---
 .../nlohmann/detail/conversions/to_json.hpp   | 10 ++++++++++
 single_include/nlohmann/json.hpp              | 19 ++++++++++++++++---
 test/src/unit-regression.cpp                  |  5 +++--
 3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp
index ce2bc0aa..e8e09015 100644
--- a/include/nlohmann/detail/conversions/to_json.hpp
+++ b/include/nlohmann/detail/conversions/to_json.hpp
@@ -284,6 +284,16 @@ void to_json(BasicJsonType& j, const std::pair<Args...>& p)
     j = {p.first, p.second};
 }
 
+template<typename IteratorType> class iteration_proxy; // TODO: Forward decl needed, maybe move somewhere else
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
+void to_json(BasicJsonType& j, T b) noexcept
+{
+    typename BasicJsonType::object_t tmp_obj;
+    tmp_obj[b.key()] = b.value(); // TODO: maybe there is a better way?
+    external_constructor<value_t::object>::construct(j, std::move(tmp_obj));
+}
+
 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
 {
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index ce534f34..bbba0292 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -1516,6 +1516,16 @@ void to_json(BasicJsonType& j, const std::pair<Args...>& p)
     j = {p.first, p.second};
 }
 
+template<typename IteratorType> class iteration_proxy; // TODO: Forward decl needed, maybe move somewhere else
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
+void to_json(BasicJsonType& j, T b) noexcept
+{
+    typename BasicJsonType::object_t tmp_obj;
+    tmp_obj[b.key()] = b.value(); // TODO: maybe there is a better way?
+    external_constructor<value_t::object>::construct(j, std::move(tmp_obj));
+}
+
 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
 void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
 {
@@ -7393,7 +7403,7 @@ boundaries compute_boundaries(FloatType value)
     constexpr int      kMinExp    = 1 - kBias;
     constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
 
-    using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
+    using bits_type = typename std::conditional<kPrecision == 24, uint32_t, uint64_t>::type;
 
     const uint64_t bits = reinterpret_bits<bits_type>(value);
     const uint64_t E = bits >> (kPrecision - 1);
@@ -7804,7 +7814,10 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
     //         = ((p1        ) * 2^-e + (p2        )) * 2^e
     //         = p1 + p2 * 2^e
 
-    const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
+    const diyfp one(uint64_t
+    {
+        1
+    } << -M_plus.e, M_plus.e);
 
     uint32_t p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
     uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
@@ -17268,7 +17281,7 @@ struct hash<nlohmann::json>
 /// @note: do not remove the space after '<',
 ///        see https://github.com/nlohmann/json/pull/679
 template<>
-struct less< ::nlohmann::detail::value_t>
+struct less<::nlohmann::detail::value_t>
 {
     /*!
     @brief compare two value_t enum values
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index d26e0e57..cea8dd87 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -1631,9 +1631,10 @@ TEST_CASE("regression tests")
             p2.begin(), p2.end(),
             std::inserter(diffs, diffs.end()), [&](const it_type & e1, const it_type & e2) -> bool
         {
-            return (e1.key() < e2.key()) and (e1.value() < e2.value());
+            using comper_pair = std::pair<std::string, decltype(e1.value())>; // Trying to avoid unneeded copy
+            return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value()); // Using pair comper
         });
 
-        CHECK(diffs.size() == 2);
+        CHECK(diffs.size() == 1); // Note the change here, was 2
     }
 }