1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
#include <iostream>
template < typename C, typename T = std::char_traits<C> >
struct basic_teebuf : public std::basic_streambuf<C,T>
{
typedef std::basic_streambuf<C,T> streambuf_type ;
typedef typename T::int_type int_type ;
basic_teebuf( streambuf_type* buff_a, streambuf_type* buff_b )
: first(buff_a), second(buff_b) {}
protected:
virtual int_type overflow( int_type c )
{
const int_type eof = T::eof() ;
if( T::eq_int_type( c, eof ) ) return T::not_eof(c) ;
else
{
const C ch = T::to_char_type(c) ;
if( T::eq_int_type( first->sputc(ch), eof ) ||
T::eq_int_type( second->sputc(ch), eof ) )
return eof ;
else return c ;
}
}
virtual int sync()
{ return !first->pubsync() && !second->pubsync() ? 0 : -1 ; }
private:
streambuf_type* first ;
streambuf_type* second ;
};
template < typename C, typename T = std::char_traits<C> >
struct basic_teestream : public std::basic_ostream<C,T>
{
typedef std::basic_ostream<C,T> stream_type ;
typedef basic_teebuf<C,T> streambuff_type ;
basic_teestream( stream_type& first, stream_type& second )
: stream_type(&stmbuf), stmbuf( first.rdbuf(), second.rdbuf() ) {}
basic_teestream( streambuff_type* first, streambuff_type* second )
: stream_type(&stmbuf), stmbuf(first,second ) {}
~basic_teestream() { stmbuf.pubsync() ; }
private: streambuff_type stmbuf ;
};
typedef basic_teebuf<char> teebuf ;
typedef basic_teestream<char> teestream ;
#include <fstream>
#include <iomanip>
int main()
{
std::ofstream file( "out.txt" ) ;
teestream tee( std::cout, file ) ; // tee to both file and stdout
tee << "hello world!\n" << 1234 << '\n'
<< std::fixed << std::setprecision(2) << 123.4567 << '\n' << std::flush ;
}
|