. -,
stringstream , .
. -,
operator<< ostream&, stringstream,
stringstream ostream& (
round), stringstream ( stringstream&)
. , , operator<<,
stringstream ,
LogStream . ,
. operator<< ,
ostream& non-const ,
. ( ,
, std::ostringstream;
, <<, char
const[] char const* .)
.
:
void LogStream( std::ostream& text )
{
std::ostringstream& s = dynamic_cast<std::ostringstream&>(text);
m_FileHandle << s.str() << std::endl;
}
, ;
, - :
m_LogObject->LogStream( std::ostringstream().flush() << "..." << x );
( std::ostream::flush()
, std::ostream&.
,
non-const member.)
. LogStreamer
- :
class LogStreamer
{
boost::shared_ptr< std::ostream > m_collector;
std::ostream* m_dest;
public:
LogStreamer( std::ostream& dest )
, m_collector( new std::ostringstream )
, m_dest( &dest )
{
}
~LogStreamer()
{
if ( m_collector.unique() ) {
*m_dest << m_collector->str() << std::endl;
}
}
template <typename T>
LogStreamer& operator<<( T const& value )
{
*m_collector << value;
return *this;
}
};
LogStreamer LogStream() { return LogStreamer( m_FileHandle ); }
:
m_LogObject->LogStream() << "..." << x;
: ,
, __FILE__ __LINE__ LogStream()
, - streambuf
, LogStream(),
,
.
streambuf - :
class LogFilter : public std::streambuf
{
std::streambuf* m_finalDest;
std::string m_currentHeader;
bool m_isAtStartOfLine;
protected:
virtual int overflow( int ch )
{
if ( m_isAtStartOfLine ) {
m_finalDest->sputn( m_currentHeader.data(), m_currentHeader.size() );
m_currentHeader = " ";
}
m_isAtStartOfLine = (ch == '\n');
return m_finalDest->sputc( ch );
}
virtual int sync()
{
return m_finalDest->sync();
}
public:
LogFilter( std::streambuf* dest )
: m_finalDest( dest )
, m_currentHeader( "" )
, m_isAtStartOfLine( true )
{
}
void startEntry( char const* filename, int lineNumber )
{
std::ostringstream header;
header << now() << ": " << filename << " (" << lineNumber << "): ";
m_currentHeader = header.str();
}
};
( now(), , a std::string
. a struct tm, << tm.)