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