Created
May 13, 2016 21:04
-
-
Save eskil/fc24d6c48810206963fca5f76ba142fb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sstream> | |
#include <iostream> | |
#include <string> | |
#include <vector> | |
template<typename InIt, typename Tdelim, typename Tj> | |
Tj& join (InIt first, InIt last, const Tdelim &d, Tj &j) { | |
if (first == last) | |
return j; | |
InIt next = first; | |
while (++next != last) { | |
j << *first << d; | |
first = next; | |
} | |
j << *first; | |
return j; | |
} | |
/** | |
* @brief Provides output iterator semantics for streams. | |
* | |
* This class provides an iterator to write to an ostream. The type Tp is | |
* the only type written by this iterator and there must be an | |
* operator<<(Tp) defined. | |
* | |
* @param Tp The type to write to the ostream. | |
* @param CharT The ostream char_type. | |
* @param Traits The ostream char_traits. | |
*/ | |
template<typename _Tp, typename _CharT = char, | |
typename _Traits = std::char_traits<_CharT> > | |
class ostream_join_iterator | |
: public std::iterator<std::output_iterator_tag, void, void, void, void> | |
{ | |
public: | |
//@{ | |
/// Public typedef | |
typedef _CharT char_type; | |
typedef _Traits traits_type; | |
typedef std::basic_ostream<_CharT, _Traits> ostream_type; | |
//@} | |
private: | |
ostream_type* _M_stream; | |
const _CharT* _M_string; | |
bool _M_first; | |
public: | |
/// Construct from an ostream. | |
ostream_join_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0), _M_first (false) {} | |
/** | |
* Construct from an ostream. | |
* | |
* The delimiter string @a c is written to the stream after every Tp | |
* written to the stream. The delimiter is not copied, and thus must | |
* not be destroyed while this iterator is in use. | |
* | |
* @param s Underlying ostream to write to. | |
* @param c CharT delimiter string to insert. | |
*/ | |
ostream_join_iterator(ostream_type& __s, const _CharT* __c) | |
: _M_stream(&__s), _M_string(__c), _M_first (true) { } | |
/// Copy constructor. | |
ostream_join_iterator(const ostream_join_iterator& __obj) | |
: _M_stream(__obj._M_stream), _M_string(__obj._M_string), _M_first (__obj._M_first) { } | |
/// Writes @a value to underlying ostream using operator<<. If | |
/// constructed with delimiter string, writes delimiter to ostream. | |
ostream_join_iterator& | |
operator=(const _Tp& __value) | |
{ | |
__glibcxx_requires_cond(_M_stream != 0, | |
_M_message(__gnu_debug::__msg_output_ostream) | |
._M_iterator(*this)); | |
if (_M_string && !_M_first) *_M_stream << _M_string; | |
*_M_stream << __value; | |
_M_first = false; | |
return *this; | |
} | |
ostream_join_iterator& | |
operator*() | |
{ return *this; } | |
ostream_join_iterator& | |
operator++() | |
{ return *this; } | |
ostream_join_iterator& | |
operator++(int) | |
{ return *this; } | |
}; | |
int main (int argc, char *argv[]) { | |
std::vector<std::string> strings (argv + 1, argv + argc); | |
{ | |
std::ostringstream res; | |
std::cout << join (strings.begin (), strings.end (), ", ", res).str () << "\n"; | |
} | |
{ | |
std::ostringstream res; | |
std::copy (strings.begin (), strings.end (), ostream_join_iterator<std::string> (res, ", ")); | |
std:: cout << res.str () << "\n"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment