OwnedArray and SLT's remove function


#1

I’m trying to increase my usage of STL algorithms to avoid reinventing wheels. I use JUCE’s OwnedArray class in certain places, but I’ve found that the .end() and .begin() methods in Array and OwnedArray make using STL algorithms quite seamless.

Now I’ve run into a problem. I have an OwnedArray where I want to remove elements that match a certain criteria. This is a perfect fit for std::remove_if, which lets you use a lambda predicate, very convenient. After remove_if (which just moves elements which match the predicate to the end and returns an iterator to the point where the matched elements begin) the normal STL thing would be to call erase() on the container. I have replaced this with a call to ownedArray.removeLast (ownedArray.end() - firstMatchedElementIterator).

This appears to work fine, but later when I call a virtual method on one of the remaining elements (it’s a polymorphous list of objects) I get a bad access error. Is the STL algorithm moving pointer elements somehow causing the program to think the object is the wrong type? Or is there something wrong with the pointer arithmetic I’m doing on the iterators?


#2

Is it because the value returned by begin() becomes invalid when you delete an item?


#3

I’m not using the .begin() iterator to access afterwards, it’s in a separate function which basically does:

if (!ownedArray.empty())
    ownedArray[0]->virtualFunction()

#4

Ah, don’t know then. Would need to see all the code to figure that out.


#5

Yeah, perhaps I should try a std::vector of unique_ptrs to see if it’s the JUCE containers or (more likely) something else in my code that’s causing the problem…


#6

Well rather than switch to a std::vector of unique_ptrs, which would have required minor changes in lots of places, I just rolled my own ugly version of remove_if:

Array<MyBaseClass*> toRemove;
        
for (int i = 0; i != uGenViews.size(); ++i)
    if (ownedArray[i]->match()))
        toRemove.add (ownedArray[i]);
        
for (int i = 0; i != toRemove.size(); ++i)
    ownedArray.removeObject (toRemove[i]);

Which solves the problem. This was the kind of code I was trying to avoid writing, and it’s certainly going to be less efficient, though that doesn’t really matter in this case, the OwnedArray will rarely have more than 20 or so items, and this isn’t hot code.