C++11 style iteration for MidiBuffer

Would it be possible/sensible to implement support for the C++11 range based for loops in the MidiBuffer class? At the moment, having to use the MidiBuffer::Iterator etc is somewhat painful and messy.

2 Likes

Yes please… +1

It’s a little bit awkward because it needs to return both a message and time, but I guess the value the iterator produces could be a struct with a buffer pointer, size and time.

1 Like

or a std::pair<MidiBuffer, int>?

Not really - you don’t really want to be passing a by-value copy of the message around, because this will often be called on the audio thread

1 Like

This will be included in JUCE 6 (we got there in the end!)

2 Likes

Hi,
That was a great idea. Can you overload the “->” operator in MidiBufferIterator too?

I’m thinking of this case where I need access to the iterator to jump to a specific sample inside the loop:

for (auto midiMessageIt = midiMessages.begin(); midiMessageIt != midiMessages.end(); ++midiMessageIt) {
   const MidiMessage m = midiMessageIt->getMessage();
   const int mPos = midiMessageIt->samplePosition;
   if (jump)
        midiMessageIt=midiMessages.findNextSamplePosition(futureSample);       
}

Would be slightly cleaner than the current:

for (auto midiMessageIt = midiMessages.begin(); midiMessageIt != midiMessages.end(); ++midiMessageIt) {
   const MidiMessageMetadata metadata = *midiMessageIt;
   const MidiMessage m = metadata.getMessage();
   const int mPos = metadata.samplePosition;
   if (jump)
        midiMessageIt=midiMessages.findNextSamplePosition(futureSample);       
}

Thanks!

Unfortunately we can’t do this easily - operator-> normally returns a pointer to whatever operator* returns. In the case of MidiBufferIterator, operator* returns a temporary, so operator-> (if it existed) would return a pointer to a temporary, so that’s not viable. We could instead keep a copy of MidiMessageMetadata inside the iterator and return a pointer to that, but that would weigh down the iterator objects and ideally those should be very cheap to copy around.

In the absence of operator-> you can still get at the message with a single line:

const auto message = (*it).getMessage();
1 Like

Got it. I agree that it is better to keep the iterator object light and that (*it).getMessage() is simple enough.