negozio di questo codice via in modo sicuro in un file di intestazione nel tuo piccolo sacchetto di utility:
namespace detail {
template<class Iter>
struct sequence_emitter
{
sequence_emitter(Iter first, Iter last, std::string sep)
: _first(std::move(first))
, _last(std::move(last))
, _sep(std::move(sep))
{}
void write(std::ostream& os) const {
bool first_element = true;
for (auto current = _first ; current != _last ; ++current, first_element = false)
{
if (!first_element)
os << _sep;
os << *current;
}
}
private:
Iter _first, _last;
std::string _sep;
};
template<class Iter>
std::ostream& operator<<(std::ostream& os, const sequence_emitter<Iter>& se) {
se.write(os);
return os;
}
}
template<class Iter>
detail::sequence_emitter<Iter>
emit_sequence(Iter first, Iter last, std::string separator = ", ")
{
return detail::sequence_emitter<Iter>(std::move(first), std::move(last), std::move(separator));
}
allora si può emettere qualsiasi intervallo di qualsiasi contenitore senza un separatore finale in questo modo:
vector<int> x { 0, 1, 2, 3, 4, 5 };
cout << emit_sequence(begin(x), end(x)) << endl;
set<string> s { "foo", "bar", "baz" };
cout << emit_sequence(begin(s), end(s), " comes before ") << endl;
risultato atteso:
0, 1, 2, 3, 4, 5
bar comes before baz comes before foo
fonte
2014-12-21 00:58:03
Solo una nota: invece di controllare se sei sull'ultimo elemento, puoi spostare la stampa di "," all'inizio del corpo del ciclo e controllare se sei sul primo elemento. È facile da fare impostando 'bool first = true;' prima del ciclo e impostando 'first = false;' all'interno del corpo del loop. – hvd
Perché non utilizzare il ['ostream_joiner'] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4336.html#iterator.ostream.joiner) dai Fondamenti? –