Simple string joiner in modern C++ - follow-up
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;
}