Simple string joiner in modern C++ - follow-up (See the previous iteration.)

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 &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &lt;iterator&gt;
#include &lt;sstream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;

using std::cout;
using std::endl;
using std::for_each;
using std::vector;

using namespace std;

template &lt;typename T, typename charT=char, typename traits=char_traits&lt;charT&gt;&gt;
class my_ostream_iterator :
public iterator&lt;output_iterator_tag, void, void, void, void&gt;
{
    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&lt;T,charT,traits&gt;&amp; operator= (const T&amp; value) {
        if (!first_value_appended)
        {
            *oss &lt;&lt; value;
            first_value_appended = true;
        }
        else
        {
            *oss &lt;&lt; *separator &lt;&lt; value;
        }

        return *this;
    }

    my_ostream_iterator&lt;T,charT,traits&gt;&amp; operator*()     { return *this; }
    my_ostream_iterator&lt;T,charT,traits&gt;&amp; operator++()    { return *this; }
    my_ostream_iterator&lt;T,charT,traits&gt;&amp; operator++(int) { return *this; }
};

template&lt;typename InputIt&gt;
std::string join(InputIt begin,
                 InputIt end,
                 const std::string&amp; separator =", ",
                 const std::string&amp; concluder ="")
{
    std::ostringstream ss;
    std::string sep = separator;
    using value_type = typename std::iterator_traits&lt;InputIt&gt;::value_type;

    std::copy(begin,
              end,
              my_ostream_iterator&lt;value_type&gt;(&amp;ss, &amp;sep));

    ss &lt;&lt; concluder;
    return ss.str();
}

int main() {
    vector&lt;vector&lt;int&gt;&gt; matrix = {
        { 1, 2, 3 },
        { 4, 5 },
        { },
        { 10, 26, 29 }
    };

    for_each(matrix.cbegin(),
             matrix.cend(),
             [](std::vector&lt;int&gt; a) {
                 cout &lt;&lt; join(a.cbegin(), a.cend()) &lt;&lt; endl;
             });
}


As always, any critique is much appreciated.
using declarations

Don't do this at top level:

using namespace std;


and certainly not in a header file, where it can can bring unexpected names into user code.

using std::cout;
using std::endl;
using std::for_each;
using std::vector;


These are less dangerous, but should still be avoided in headers.  Reduce their scope and visibility as much as you can, or use fully-qualified names.

Pointers and ownership

std::ostringstream* oss;
std::string* separator;


Who owns these objects?  Can they be null?  oss is used without checking for null, and it does not appear to be owned by this, so it should probably be a reference.  separator should probably be an owned value, so you can initialize from an rvalue.

Type of separator

Why is separator a std::string?  If the output stream can handle wide strings, we should be able to separate our values with wide strings.

Usual operator types

g++ -Weffc++ recommends that you return the result of postincrement by value, rather then by reference.  That's arguably moot in this case, as incrementing is a no-op, but I like to avoid warnings!

Code duplication

It's a small duplication, but I think it's clearer to separate out the emitting of separator and value:

my_ostream_iterator&lt;T,charT,traits&gt;&amp; operator= (const T&amp; value) {
    if (first_value_appended)
        oss &lt;&lt; separator;
    else
        first_value_appended = true;

    oss &lt;&lt; value;
    return *this;
}


Generality

Your iterator is templated on the character type, but you don't seem to make use of that type (see "type of separator" above).  I prefer to make the output stream a std::basic_ostringstream&lt;CharT, Traits&gt; so that your code will produce the correct kind of string as output.

Efficiency

In your std::for_each in main(), you pass a vector by value.  It should probably be a reference to const vector.



Modified code

#include &lt;iterator&gt;
#include &lt;sstream&gt;
#include &lt;string&gt;

template&lt;typename T, typename CharT=char, typename Traits=std::char_traits&lt;CharT&gt;&gt;
class my_ostream_iterator
    : public std::iterator&lt;std::output_iterator_tag, void, void, void, void&gt;
{
    using string_t = std::basic_string&lt;CharT, Traits&gt;;
    using stream_t = std::basic_ostringstream&lt;CharT, Traits&gt;;

    stream_t&amp; oss;
    const string_t separator;
    bool first_value_appended;

public:

    my_ostream_iterator(stream_t&amp; oss, const string_t&amp; separator)
        : oss{oss},
          separator{separator},
          first_value_appended{false}
    {
    }

    my_ostream_iterator&lt;T,CharT,Traits&gt;&amp; operator= (const T&amp; value) {
        if (first_value_appended)
            oss &lt;&lt; separator;
        else
            first_value_appended = true;

        oss &lt;&lt; value;
        return *this;
    }

    my_ostream_iterator&lt;T,CharT,Traits&gt;&amp; operator*()     { return *this; }
    my_ostream_iterator&lt;T,CharT,Traits&gt;&amp; operator++()    { return *this; }
    my_ostream_iterator&lt;T,CharT,Traits&gt; operator++(int)  { return *this; }
};

template&lt;typename InputIt, typename StringT = std::string&gt;
StringT join(InputIt begin,
             InputIt end,
             const StringT&amp; separator = ", ",
             const StringT&amp; concluder = {})
{
    using value_type = typename std::iterator_traits&lt;InputIt&gt;::value_type;
    using char_type = typename StringT::value_type;

    std::basic_ostringstream&lt;char_type&gt; ss;
    std::copy(begin, end,
              my_ostream_iterator&lt;value_type, char_type&gt;(ss, separator));

    ss &lt;&lt; concluder;
    return ss.str();
}


// test program
#include &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;

int main() {
    // Bring in names needed for argument-dependent lookup
    using std::begin;
    using std::end;

    const std::vector&lt;std::vector&lt;int&gt;&gt; matrix = {
        { 1, 2, 3 },
        { 4, 5 },
        { },
        { 10, 26, 29 }
    };

    std::for_each(begin(matrix), end(matrix),
                  [](const auto&amp; a) {
                      std::cout &lt;&lt; join(begin(a), end(a)) &lt;&lt; std::endl;
                  });
    std::cout &lt;&lt; " ---" &lt;&lt; std::endl;

    std::for_each(begin(matrix), end(matrix),
                  [](const auto&amp; a) {
                      std::wcout &lt;&lt; join(begin(a), end(a), std::wstring(L", ")) &lt;&lt; std::endl;
                  });
    std::wcout &lt;&lt; " ---" &lt;&lt; std::endl;
}