Skip to content

Commit

Permalink
💩 first try on #1045
Browse files Browse the repository at this point in the history
  • Loading branch information
nlohmann committed Apr 10, 2018
1 parent acf10d9 commit 8d8f890
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
17 changes: 17 additions & 0 deletions include/nlohmann/detail/iterators/iteration_proxy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cstddef> // size_t
#include <string> // string, to_string
#include <iterator> // input_iterator_tag

#include <nlohmann/detail/value_t.hpp>

Expand All @@ -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;

This comment has been minimized.

Copy link
@theodelrieu

theodelrieu Apr 10, 2018

Contributor

Shouldn't that be typename IteratorType::value_type? Or did I misunderstand the point of this class?

This comment has been minimized.

Copy link
@gregmarr

gregmarr Apr 10, 2018

Contributor

Yes, value_type, pointer, and reference refer to the thing that the iterator references, not the iterator itself.

This comment has been minimized.

Copy link
@nlohmann

nlohmann Apr 10, 2018

Author Owner

Changing value_type to typename IteratorType::value_type and adjusting the result yields the same error message.

And idea of the iterator is to return something where I can call key() and value() on - so wouldn't be typename IteratorType::value_type just the type of value()?

This comment has been minimized.

Copy link
@gregmarr

gregmarr Apr 10, 2018

Contributor

Ah, didn't notice that operator* return type was the same type as the class.

This comment has been minimized.

Copy link
@theodelrieu

theodelrieu Apr 10, 2018

Contributor

Hmm in that case I think you should add iteration_proxy_internal to the is_basic_json_nested_type trait in detail/meta.hpp.

I'm kinda shooting in the dark here, but this error message reminds me of it.

This comment has been minimized.

Copy link
@nlohmann

nlohmann Apr 10, 2018

Author Owner

With that, I get a different error message:

In file included from ../test/src/unit-regression.cpp:29:
In file included from ../test/thirdparty/catch/catch.hpp:382:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/sstream:174:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/ostream:138:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/ios:216:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__locale:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:470:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string_view:169:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__string:56:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:5651:23: error: no viable overloaded '='
            *__result = *__first1;
            ~~~~~~~~~ ^ ~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:5677:12: note: in instantiation of function template specialization 'std::__1::__set_difference<(lambda at ../test/src/unit-regression.cpp:1632:48) &, nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >' requested here
    return __set_difference<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp);
           ^
../test/src/unit-regression.cpp:1629:14: note: in instantiation of function template specialization 'std::__1::set_difference<nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> >, (lambda at ../test/src/unit-regression.cpp:1632:48)>' requested here
        std::set_difference(
             ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:846:28: note: candidate function (the implicit move assignment operator) not viable: no known conversion from 'nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal' to 'std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> >' for 1st argument
class _LIBCPP_TEMPLATE_VIS insert_iterator
                           ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:846:28: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal' to 'const std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> >' for 1st argument
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:861:48: note: candidate function not viable: no known conversion from 'nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal' to 'const typename basic_json<std::map, std::vector, basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer>::value_type' (aka 'const nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer>') for 1st argument
    _LIBCPP_INLINE_VISIBILITY insert_iterator& operator=(const typename _Container::value_type& __value_)
                                               ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:864:48: note: candidate function not viable: no known conversion from 'nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal' to 'typename basic_json<std::map, std::vector, basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer>::value_type' (aka 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer>') for 1st argument
    _LIBCPP_INLINE_VISIBILITY insert_iterator& operator=(typename _Container::value_type&& __value_)
                                               ^
In file included from ../test/src/unit-regression.cpp:29:
In file included from ../test/thirdparty/catch/catch.hpp:382:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/sstream:174:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/ostream:138:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/ios:216:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__locale:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string:470:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/string_view:169:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/__string:56:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:1812:19: error: no viable overloaded '='
        *__result = *__first;
        ~~~~~~~~~ ^ ~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:1837:19: note: in instantiation of function template specialization 'std::__1::__copy<nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >' requested here
    return _VSTD::__copy(__unwrap_iter(__first), __unwrap_iter(__last), __unwrap_iter(__result));
                  ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:5648:27: note: in instantiation of function template specialization 'std::__1::copy<nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >' requested here
            return _VSTD::copy(__first1, __last1, __result);
                          ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:5677:12: note: in instantiation of function template specialization 'std::__1::__set_difference<(lambda at ../test/src/unit-regression.cpp:1632:48) &, nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >' requested here
    return __set_difference<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp);
           ^
../test/src/unit-regression.cpp:1629:14: note: in instantiation of function template specialization 'std::__1::set_difference<nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal, std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> >, (lambda at ../test/src/unit-regression.cpp:1632:48)>' requested here
        std::set_difference(
             ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:846:28: note: candidate function (the implicit move assignment operator) not viable: no known conversion from 'nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal' to 'std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> >' for 1st argument
class _LIBCPP_TEMPLATE_VIS insert_iterator
                           ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:846:28: note: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal' to 'const std::__1::insert_iterator<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> >' for 1st argument
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:861:48: note: candidate function not viable: no known conversion from 'nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal' to 'const typename basic_json<std::map, std::vector, basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer>::value_type' (aka 'const nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer>') for 1st argument
    _LIBCPP_INLINE_VISIBILITY insert_iterator& operator=(const typename _Container::value_type& __value_)
                                               ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/iterator:864:48: note: candidate function not viable: no known conversion from 'nlohmann::detail::iteration_proxy<nlohmann::detail::iter_impl<nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer> > >::iteration_proxy_internal' to 'typename basic_json<std::map, std::vector, basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer>::value_type' (aka 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, unsigned long long, double, std::allocator, adl_serializer>') for 1st argument
    _LIBCPP_INLINE_VISIBILITY insert_iterator& operator=(typename _Container::value_type&& __value_)
using pointer = iteration_proxy_internal*;
using reference = iteration_proxy_internal&;
using iterator_category = std::input_iterator_tag;

private:
/// the iterator
IteratorType anchor;
Expand All @@ -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*()
{
Expand All @@ -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
{
Expand Down
17 changes: 17 additions & 0 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand All @@ -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;
Expand All @@ -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*()
{
Expand All @@ -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
{
Expand Down
21 changes: 21 additions & 0 deletions test/src/unit-regression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

0 comments on commit 8d8f890

Please sign in to comment.