In c++17/g++7, there's finally the long missed ostream_joiner. It enables proper output to ostreams, separating collection elements with infix delimiters.
#include <algorithm>
#include <experimental/iterator>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
using string = std::string;
#if 1
struct pair {
string first;
string second;
};
#else
using pair = std::pair<string,string>;
#endif
std::ostream& operator<<(std::ostream& lhs, const pair &p) {
return lhs << p.first << "=" << p.second;
}
int main()
{
std::vector<pair> pairs = {{"foo", "bar"}, {"baz", "42"}};
std::copy(std::begin(pairs),
std::end(pairs),
std::experimental::make_ostream_joiner(std::cout, ", "));
}
Whilst the code piece succesfully compiles and outputs ...
foo=bar, baz=42
... changing the #if 1 to a #if 0 in the snippet makes the compiler complaining about missing the proper shift operator:
main.cpp:29:70: required from here
/usr/local/include/c++/7.2.0/experimental/iterator:88:10: error: no match for
'operator<<' (operand types are
'std::experimental::fundamentals_v2::ostream_joiner<const char*, char,
std::char_traits<char> >::ostream_type {aka std::basic_ostream<char>}' and
'const std::pair<std::__cxx11::basic_string<char>,
std::__cxx11::basic_string<char> >')
*_M_out << __value;
Does somebody have a clue why?
update
Barry has given the right answer to the question. It however does not solve the problem, and running a manual loop is not in the sense of reusing existing stl code, so the question gets extended to:
Is it possible to make the stream operator work without polluting the std namespace?