Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support C++11 range-based loop #162

Closed
drewnoakes opened this issue Oct 17, 2014 · 10 comments
Closed

Support C++11 range-based loop #162

drewnoakes opened this issue Oct 17, 2014 · 10 comments
Milestone

Comments

@drewnoakes
Copy link
Contributor

Currently the for(auto item& : myValue) loop is not supported by rapidjson. I guess this is because the case of Begin and End does not match what the standard expects.

I'd like to use this for array iteration, though I suspect it could also be useful over members as well.

@pah
Copy link
Contributor

pah commented Oct 17, 2014

This can be achieved by simply adding the following four functions to the rapidjson namespace:

namespace rapidjson {
template <typename Encoding, typename Allocator>
typename GenericValue<Encoding,Allocator>::ValueIterator begin(GenericValue<Encoding,Allocator>& v) { return v.Begin(); }
template <typename Encoding, typename Allocator>
typename GenericValue<Encoding,Allocator>::ConstValueIterator begin(const GenericValue<Encoding,Allocator>& v) { return v.Begin(); }

template <typename Encoding, typename Allocator>
typename GenericValue<Encoding,Allocator>::ValueIterator end(GenericValue<Encoding,Allocator>& v) { return v.End(); }
template <typename Encoding, typename Allocator>
typename GenericValue<Encoding,Allocator>::ConstValueIterator end(const GenericValue<Encoding,Allocator>& v) { return v.End(); }
} // namespace rapidjson

I'm not sure, if adding this to the core library is sufficient, though. GenericValue is a variant type, which should at least allow you to select the "iteration type" you want to use: array element vs. object members.

@drewnoakes
Copy link
Contributor Author

Thanks @pah, this is great.

Would there be any overhead of confusion from the following new API?

for (auto& item : doc.ArrayItems()) {}
for (auto& member : doc.Members()) {}

@pah
Copy link
Contributor

pah commented Oct 17, 2014

Yes, something like this could be an option.

I thought of shallow wrapper objects returned by functions GetArray()/ GetObject() (symmetric to GetInt, etc.), restricting access to a GenericValue to the specific type and adding additional convenience APIs like range-loop support.

@lichray
Copy link
Contributor

lichray commented Oct 23, 2014

boost::make_iterator_range(doc.Begin(), doc.End())
boost::make_iterator_range(doc.MemberBegin(), doc.MemberEnd())

So that you can do it even with free functions.

@weepy
Copy link

weepy commented Apr 1, 2015

+1

1 similar comment
@evil-jester
Copy link

+1

@miloyip
Copy link
Collaborator

miloyip commented Feb 14, 2016

@pah Your idea of GetArray()/GetObject has been implemented in PR #542 .
Please review the PR when you have time. Thank you.

@miloyip
Copy link
Collaborator

miloyip commented Feb 20, 2016

Merged #542

@miloyip miloyip closed this as completed Feb 20, 2016
@kklouzal
Copy link

kklouzal commented Nov 3, 2017

As mentioned in the first post, the capitalization of B and E on Begin() and End() functions are preventing auto ranged based for looping. for (auto Val : Doc).

I've attempted to change them to lowercase myself however at that point the compiler starts telling you you're trying to access private/protected member functions when you shouldn't be..

@pah
Copy link
Contributor

pah commented Nov 3, 2017

Two things to note here:

  • You can use GetArray()/GetObject() functions to use range-based for over arrays or objects:
  • As RapidJSON value are generally not copyable, you should loop over references instead
  Document doc;
  // ... fill the array
  for( const auto& e : doc.GetArray() ) // loop over array
     std::cout << e.GetInt() << std::endl;

  // ... fill an object
  for( auto& m : doc.GetObject() ) // loop over object (non-const)
    m.value.SetNull(); // modify entry 

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants