This is an old question but I noticed that a couple of people used two explicit tests to stop the last comma from appearing. That's unnecessary. Only need to test if the vector is not empty. If the vector contains one element then the copy becomes a no-op.
std::vector<std::string> V { "A", "B", "C", "D" };
if (!V.empty()) {
std::copy(V.begin(), V.end() - 1, std::ostream_iterator<std::string>(std::cout, ", "));
std::cout << V.back();
}
If you want a function that takes begin and end args:
template<typename OS, typename IT>
OS& csv(OS& os, IT begin, IT end, char const* delim = ", ") {
if (begin != end) {
using value_type = typename std::iterator_traits<IT>::value_type;
std::copy(begin, end - 1, std::ostream_iterator<value_type>(os, delim));
os << end[-1];
}
return os;
}