mercredi 27 septembre 2017

How do I walk a bidirectional iterator backwards in clean code?

Suppose I have an std::map and want to do something to the item with key X and every item with a higher key (remember, this is an ordered map). The code is obvious and clear:

auto iter = mymap.find(X);
while (iter != mymap.end()) {
    process(*iter);
    iter++;
}

or, possibly better, std::for_each(mymap.find(X), mymap.end(), process).

But if my task is to perform processing on the item with key X and every item with a lower key, in that order, I can't find a clean coding pattern that expresses intent.

auto iter mymap.find(x);
if (iter != mymap.end()) {
    iter++;                           // Go forward...
    while (iter != mymap.begin()) {
        iter--;                       // ... so we can go backwards
        process(*iter);
    }
}

If I didn't want to do them in reverse order, it would be easy enough to increment the iterator returned by std::map::find() and then use std::for_each(mymap.begin(), incremented_iter, process).

Bidirectional iterators aren't reverse iterators, so I can't use mymap.rend() as the "off the beginning" to compare against in a while() loop.

Is there a clean way to do this in C++11 (or in +14 or +17, so I'll have something to look forward to)?

Aucun commentaire:

Enregistrer un commentaire