Std::iterator_traits for JUCE container types

I want to use the super handy functions in <algorithm> with JUCE classes like Array and ValueTree, but I can’t because their iterators are extremely basic and lack definitions for things like difference_type. Any chance we can get these so we can leverage the STL’s algorithms from JUCE containers?

3 Likes

What STL stuff does this entail?

edit: I’m a dummy, cppreference ftw:

How about I do some legwork here and you write the UnitTests, @jonathonracz?

Sure! Hit me with a PM or post here when you’ve got something.

I’m in a hurry on this so I whipped up a version for ValueTree objects:

To the JUCE team: all that needs to be added to make the JUCE iterators ForwardIterator compatible are typedefs for value_type, difference_type, reference, pointer, and iterator_category. The iterator in the gist above is simply a 1:1 wrapper around ValueTree::Iterator with those definitions added, and now I’m zooming around in ValueTree with <algorithm> functions!

Not bad! We can make it bidi with a few more methods. If you want to cut some redundancy and make it look more standard, derive the iterator as such: public std::iterator<std::forward_iterator_tag, void>, and remove your typedefs.

I would’ve but std::iterator is deprecated in C++17 :stuck_out_tongue:

http://en.cppreference.com/w/cpp/iterator/iterator

Why not add the typedefs to ValueTree::Iterator directly instead of making a wrapper?

I avoid modifying JUCE library code at all costs so I don’t have to maintain my own branch or otherwise try to keep track of changes I’m making per-project.

Instead, I always try to create workarounds to non destructively extend JUCE functionality so myself and others can easily integrate them. My best (yet unreleased) example of this is my accessibility module, which uses a bunch of clever listener techniques to hook native OS accessibility hierarchies into JUCE’s Component hierarchy. :smiley:

So the idea was not to get this contributed into JUCE?

I would be very happy to help you, but like you, I don’t like maintaining my own branch, so I just prefer contributing back into upstream ASAP.

In almost all cases I’ve seen over the years, contributing to JUCE operates at a glacial pace (especially when it’s a feature addition). Additionally, since I’m not a paying customer (just a student who uses it for 100% of my open source/academic work) I’m at the bottom of the pecking order to get the team’s attention.

It’s only like 5 lines of typedefs, my hope is someone will see it and add it to the ValueTree::Iterator if they deem it necessary. Since I work 24/7/365 and I can’t move forward until I have this iterator, I went ahead and whipped up a quick workaround.

1 Like

That’s a bit unfair, we’re often very quick if it’s something straightforward!

Certainly adding some typedefs to ValueTree::Iterator is a good idea, I can do that. I’m guessing that these would be enough for the use-cases that you’ve tested?

    using difference_type    = std::ptrdiff_t;
    using value_type         = ValueTree;
    using reference          = ValueTree&;
    using pointer            = ValueTree*;
    using iterator_category  = std::forward_iterator_tag;

Yes I am being a bit hyperbolic, if it really was that slow for trivial additions I wouldn’t be sticking around I suppose. I’m aware the JUCE team seems a little understaffed and overworked with demands coming in from ROLI, paying customers, freeloaders like myself.

And yes, those are the necessary typedefs - while I know using x = y is semantically identical to typedef, I didn’t try it with that. Knowing how picky extending the STL can be, try tossing it at some <algorithm> functions to test it out to make sure I didn’t miss anything.

Additionally, Array and other JUCE containers with iterators could use these at some point - it gets marginally hairier since templated types become involved. Another consideration is that certain algorithms can be made much faster by supporting random access iterators (which from my understanding are a superset of std::forward_iterator) which would be a nice future addition.

Any news on adding this…?

BTW, I ended up needing these extra traits for the Array classes too, so I made a set of Iterator objects for those as well which are almost identical to the gist in my prior post. FWIW I used the using keyword instead of typedef and it worked fine (as it should since they’re supposed to be semantically identical).

So long as the definitions are getting added, it would be nice if we could get some iterator qualifiers past the simple ForwardIterator in. Some algorithms in the STL run faster with BidirectionalIterator or RandomAcessIterator, which I’m pretty sure most JUCE containers qualify for. It’s mostly just a matter of navigating the template jungle to satisfy the right definition requirements.