Каждый сталкивается с этой проблемой в какой-то момент:
for(const auto& item : items) {
cout << item << separator;
}
... и вы получите дополнительный разделитель, которого вы не хотите в конце. Иногда он не печатает, но, скажем, выполняет какое-то другое действие, но для того, чтобы последовательные действия одного и того же типа требовали какого-либо действия разделителя, но последнее не делает.
Теперь, если вы работаете со старой школой для циклов и массива, вы бы сделали
for(int i = 0; i < num_items; i++)
cout << items[i];
if (i < num_items - 1) { cout << separator; }
}
(или вы можете исключить последний элемент из цикла.) Если у вас есть что-то, что допускает неразрушающие итераторы, даже если вы не знаете его размер, вы можете сделать:
for(auto it = items.cbegin(); it != items.cend(); it++) {
cout << *it;
if (std::next(it) != items.cend()) { cout << separator; }
}
Мне не нравится эстетика последних двух, и, как правило, для петель. Могу ли я получить тот же эффект, что и с двумя последними, но используя более сильные конструкции С++ 11ish?
Чтобы расширить вопрос дальше (за пределами, скажем, этого), я скажу, что также хотел бы, чтобы явным образом не имел особого случая первый или последний элемент. Это "деталь реализации", с которой я не хочу беспокоиться. Итак, в imaginary-future-С++ возможно что-то вроде:
for(const auto& item : items) {
cout << item;
} and_between {
cout << separator;
}