(See the [previous iteration](https://codereview.stackexchange.com/questions/142902/simple-string-joiner-in-modern-c).) Now, I have defined an iterator for dumping contents of a sequence such that the last element is not followed by the separator string. **main.cpp**: #include <algorithm> #include <iostream> #include <iterator> #include <sstream> #include <string> #include <vector> using std::cout; using std::endl; using std::for_each; using std::vector; using namespace std; template <typename T, typename charT=char, typename traits=char_traits<charT>> class my_ostream_iterator : public iterator<output_iterator_tag, void, void, void, void> { std::ostringstream* oss; std::string* separator; bool first_value_appended; public: my_ostream_iterator(std::ostringstream* oss_, std::string* separator_) : oss{oss_}, separator{separator_}, first_value_appended{false} {} my_ostream_iterator<T,charT,traits>& operator= (const T& value) { if (!first_value_appended) { *oss << value; first_value_appended = true; } else { *oss << *separator << value; } return *this; } my_ostream_iterator<T,charT,traits>& operator*() { return *this; } my_ostream_iterator<T,charT,traits>& operator++() { return *this; } my_ostream_iterator<T,charT,traits>& operator++(int) { return *this; } }; template<typename InputIt> std::string join(InputIt begin, InputIt end, const std::string& separator =", ", const std::string& concluder ="") { std::ostringstream ss; std::string sep = separator; using value_type = typename std::iterator_traits<InputIt>::value_type; std::copy(begin, end, my_ostream_iterator<value_type>(&ss, &sep)); ss << concluder; return ss.str(); } int main() { vector<vector<int>> matrix = { { 1, 2, 3 }, { 4, 5 }, { }, { 10, 26, 29 } }; for_each(matrix.cbegin(), matrix.cend(), [](std::vector<int> a) { cout << join(a.cbegin(), a.cend()) << endl; }); } As always, any critique is much appreciated.