Reputation: 4406
I need aliases of the last two elements in an std::list
. The last one is easy (.back()
), but how should I get the one before it?
My first idea was: get an iterator after the last element (.end()
) and the move it twice to the left. And here is what I "produced":
&last_but_one = *----myList.end(),
Although it works, I personally find it some kind of obfuscated and I don't think I would parse it easily if I saw it in someone else's code1.
Reading through this answer shows some other (too) verbose approaches2:
auto iter = n.end();
std::advance(iter, -2);
&last_but_one = *iter; // this is overkill!
// weird, and the .next() variant even more
&last_but_one = *std::prev(std::prev(n.end()));
&last_but_one = *++myList.rbegin(); // similar to *----myList.end()
Which is the prefered way of doing this?
1I could leave a comment but code should be self-explanatory.
2 and probably slower and more complex, which shouldn't be the main reason for the choice
Upvotes: 4
Views: 1699
Reputation: 303890
std::prev()
takes two arguments. You can use the second one:
auto& second_to_last = *std::prev(list.end(), 2);
This does exactly what your version with advance(iter, -2)
does, except it returns the resulting iterator instead of being void
so you can do everything you need on one line.
Upvotes: 10