Range-based for loop over ValueTree does not compile

It is extremely surprising to me that this does not compile:

juce::ValueTree tree;
for (auto& child : tree) { /* code */ }

Isn’t that due to the reference type? I don’t see anything that allows getting ValueTree children by reference even outside of iterators

yep, looks like ValueTree::Iterator isn’t really a LegacyForwardIterator because its operator* returns by value instead of by reference.

https://en.cppreference.com/w/cpp/named_req/ForwardIterator

1 Like

I suppose the iterator could be tweaked to have a private member which is the Value, and then return a reference to it rather than just creating a Value and returning it when needed, but somehow it seems icky to be returning a reference to an object that’s contained in the iterator itself…

Looks like vector<bool> also doesn’t provide iterators implementing LegacyForwardIterator, so this wouldn’t work either:

std::vector<bool> vec;
for (auto& i : vec) { /* code */ }

Perhaps one solution is just to iterate using auto&& instead.

const auto& would probably also work

1 Like

Not if you want to modify the children.

Yes, it’s exactly the same problem as with vector<bool>: the iterator does not return references to objects that exist inside the tree. Therefore, ValueTree is not a container, and range-based for loops and STL algorithms don’t work.

2 Likes

shouldn’t iterate over a normal copy just work fine because internally it isn’t a copy? so just the syntax is a little bit confusing from a cpp standpoint.

Create ValueTree objects on the stack, and don’t be afraid to copy them around, as they’re simply a lightweight reference to a shared data container. Creating a copy of another ValueTree simply creates a new reference to the same underlying object - to make a separate, deep copy of a tree you should explicitly call createCopy().