Skip to main content
replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link
Source Link
coderodde
  • 29.8k
  • 14
  • 77
  • 194

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 <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.