fork download
  1. #include <set>
  2. #include <ostream>
  3. #include <streambuf>
  4.  
  5. template< typename CharT,
  6. typename Traits = std::char_traits<CharT> >
  7. struct StreamSplitBuffer : std::basic_streambuf<CharT, Traits>
  8. {
  9. typedef std::basic_streambuf<CharT, Traits> streambuf_type;
  10. typedef std::basic_ostream<CharT, Traits> ostream_type;
  11.  
  12. ostream_type& mOriginal;
  13.  
  14. streambuf_type* const mBase;
  15. std::set<streambuf_type*> mStreambufs;
  16.  
  17. public:
  18.  
  19. StreamSplitBuffer( ostream_type& os ):
  20. mOriginal(os), // no list-initialization syntax for references
  21. mBase{os.rdbuf()}
  22. {
  23. add(mBase);
  24. mOriginal.rdbuf( this );
  25. }
  26.  
  27. ~StreamSplitBuffer()
  28. {
  29. mOriginal.rdbuf( mBase );
  30. }
  31.  
  32. typedef CharT char_type;
  33. typedef Traits traits_type;
  34.  
  35. typedef typename std::set<streambuf_type*>::iterator iterator;
  36. typedef typename std::set<streambuf_type*>::const_iterator const_iterator;
  37.  
  38. iterator begin() { return mStreambufs.begin(); }
  39. iterator end() { return mStreambufs.end(); }
  40. const_iterator begin() const { return mStreambufs.cbegin(); }
  41. const_iterator end() const { return mStreambufs.cend(); }
  42.  
  43. std::pair<iterator, bool> add( streambuf_type* ptr ) { return mStreambufs.insert(ptr); }
  44. std::pair<iterator, bool> add( ostream_type& ptr ) { return add(ptr.rdbuf()); }
  45.  
  46. void erase( iterator i ) { mStreambufs.erase(i); }
  47.  
  48. protected:
  49.  
  50. virtual typename traits_type::int_type overflow( typename traits_type::int_type c = traits_type::eof() ) override
  51. {
  52. typename traits_type::int_type rval = traits_type::not_eof(c);
  53.  
  54. if( !traits_type::eq_int_type( rval, c ) ) /// EOF - no characters to be written. Return success.
  55. return rval;
  56.  
  57. for( auto ptr : *this )
  58. if( traits_type::eq_int_type( ptr->sputc( traits_type::to_char_type(c) ), traits_type::eof() ) )
  59. rval = traits_type::eof(); // if one streambuf returns a value indicating failure, all other streambufs are done and EOF is returned.
  60.  
  61. return rval;
  62. }
  63. };
  64.  
  65. #include <iostream>
  66. #include <sstream>
  67.  
  68. int main()
  69. {
  70. StreamSplitBuffer<char> splitter(std::cout);
  71.  
  72. std::ostringstream stream;
  73. splitter.add(stream);
  74.  
  75. std::cout << "Hallo Welt!\nWie gehts?";
  76.  
  77. std::cout << '\n' << stream.str();
  78. }
Success #stdin #stdout 0s 2988KB
stdin
Standard input is empty
stdout
Hallo Welt!
Wie gehts?
Hallo Welt!
Wie gehts?