Using STL algorithms with Array

I regularly run into problems getting JUCE Arrays to work with STL set algorithms. I want to use STL as much as possible, but it’s not easy with JUCE.

For instance, this won’t compile:

    Array<int> newSet{ 1, 2, 3 },
               oldSet{ 2, 3, 4 },
               result;

        std::set_difference(newSet.begin(), newSet.end(),
                            oldSet.begin(), oldSet.end(),
                            std::back_inserter(result));

because the back_inserter can’t be created around an Array. So I often end up using std::vector instead of Array, but then I run into problems later when I have to convert one to the other element by element, which seems wasteful. I’m guessing I’m not the only person who struggles with this–it seems like it would be a common problem.

I have two questions:

  1. Is there any way to get JUCE Arrays to work with stl algorithms, ie. some other option to std::back_inserter?

  2. If not, what do people usually do? Abandon stl or find some fancy interface between vectors and Arrays?

It’s fairly trivial to write your own output iterator, maybe something like this:

template <typename Container> class BackAddIterator final {
public:
  BackAddIterator() noexcept = default;
  constexpr explicit BackAddIterator(Container &c)
      : container_(std::addressof(c)) {}

  template <typename T> constexpr BackAddIterator &operator=(T &&t) {
    container_->add(std::forward<T>(t));
    return *this;
  }

  constexpr BackAddIterator &operator*() { return *this; }
  constexpr BackAddIterator &operator++() { return *this; }
  constexpr BackAddIterator &operator++(int) { return *this; }

private:
  Container *container_{nullptr};
};

template <typename Container> constexpr auto backAdder(Container &c) {
  return BackAddIterator<Container>(c);
}

Then just call backAdder instead of std::back_inserter.

1 Like

Personally, I use std::vector whenever I need to do stuff that requires STL algorithms, or when I just want to iterate over the collection and not do anything fancy with it.

The only times I use juce::Array is when I want to use some of its convenience functions that don’t look as pretty when using STL algorithms, like addIfNotAlreadyThere or removeAllInstancesOf.

So basically, I default to using std::vectors, unless juce::Array makes the code prettier.

For context, in my current project I use std::vector 210 times, juce::Array 6 times and juce::OwnedArray 3 times.

2 Likes

Thanks for the feedback. The thing is, I’m using a lot of other JUCE functions that give me Arrays not vectors, ie. SelectedItemSet and var::getArray(). Still, its good to know that other people approach it this way. For now, building my own iterator as @reuk suggested is definitely the right thing to do. I’m glad that other people here find this “trivial”, because it would have taken me hours!