diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index be32270b..5c024ebc 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -294,6 +294,16 @@ void to_json(BasicJsonType& j, const std::pair& p) j = {p.first, p.second}; } +template class iteration_proxy; // TODO: Forward decl needed, maybe move somewhere else +template::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::construct(j, std::move(tmp_obj)); +} + template void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence) { diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp index 047e1855..f5dbb2c7 100644 --- a/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -2,6 +2,7 @@ #include // size_t #include // string, to_string +#include // input_iterator_tag #include @@ -16,6 +17,13 @@ template 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; @@ -31,6 +39,9 @@ template 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*() { @@ -46,6 +57,12 @@ template 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 880f00e4..86ac01b8 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -1606,6 +1606,16 @@ void to_json(BasicJsonType& j, const std::pair& p) j = {p.first, p.second}; } +template class iteration_proxy; // TODO: Forward decl needed, maybe move somewhere else +template::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::construct(j, std::move(tmp_obj)); +} + template void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence) { @@ -5329,6 +5339,7 @@ class iter_impl #include // size_t #include // string, to_string +#include // input_iterator_tag // #include @@ -5344,6 +5355,13 @@ template 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; @@ -5359,6 +5377,9 @@ template 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*() { @@ -5374,6 +5395,12 @@ template 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 { @@ -8544,7 +8571,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::type; const uint64_t bits = reinterpret_bits(value); const uint64_t E = bits >> (kPrecision - 1); @@ -8955,7 +8982,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(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 @@ -18475,7 +18505,7 @@ struct hash /// @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 8bdd2dc3..c0d82700 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -1581,4 +1581,26 @@ 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 + { + using comper_pair = std::pair; // Trying to avoid unneeded copy + return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value()); // Using pair comper + }); + + CHECK(diffs.size() == 1); // Note the change here, was 2 + } }