Everyone encounters this issue at some point:
for(const auto& item : items) {
cout << item << separator;
}
... and you get an extra separator you don't want at the end. Sometime it's not printing, but, say, performing some other action, but such that consecutive actions of the same type require some separator action - but the last doesn't.
Now, if you work with old-school for loops and an array, you would do
for(int i = 0; i < num_items; i++)
cout << items[i];
if (i < num_items - 1) { cout << separator; }
}
(or you could special-case the last item out of the loop.) If you have anything that admits non-destructive iterators, even if you don't know its size, you can do:
for(auto it = items.cbegin(); it != items.cend(); it++) {
cout << *it;
if (std::next(it) != items.cend()) { cout << separator; }
}
I dislike the aesthetics of the last two, and like ranged for loops. Can I obtain the same effect as with the last two but using more spiffy C++11ish constructs?
To expand the question further (beyond, say, this one), I'll say I would also like not to expressly have special-case the first or the last element. That's an "implementation detail" which I don't want to be bothered with. So, in imaginary-future-C++, maybe something like:
for(const auto& item : items) {
cout << item;
} and_between {
cout << separator;
}
join
. This is a huge shame. – Cosperfold
is not going to help you - it will apply operation for every element, including the first and the last. – Cosperstd::accumulate
when your container is empty, but one element should be just fine (the single element gets passed asinit
, andbegin == end
initially, resulting in no folds) – Ring