#include <string> #include <sstream> #include <iostream> // forward declaration struct str_stream; // ... helper - allow explicit conversion to string class as_string {}; inline std::ostream & operator<< ( std::ostream & streamOut, const as_string &) { return streamOut; } namespace Private { // what should we return when calling write_to_stream ? template< class type> struct return_from_write_to_stream { typedef const str_stream & return_type; }; template<> struct return_from_write_to_stream< as_string> { typedef std::string return_type; }; // forward declaration template< class type> inline typename return_from_write_to_stream< type>::return_type write_to_stream ( const str_stream & streamOut, const type & value); } // forward declaration template< class type> inline typename Private::return_from_write_to_stream< type>::return_type operator<< ( const str_stream & streamOut, const type & value); // str_stream - allow stream usage, and then conversion to string struct str_stream { // default construction str_stream() {} // allow to_string like usage template< class type> str_stream( const type & value) { *this << value; } std::stringstream & underlying_stream() const { return m_streamOut; } operator std::string() const { return m_streamOut.str(); } private: mutable std::stringstream m_streamOut; #ifndef NDEBUG public: void recalculate_string() const { m_string = m_streamOut.str(); } private: mutable std::string m_string; #endif }; namespace Private { template< class type> inline typename return_from_write_to_stream< type>::return_type write_to_stream ( const str_stream & streamOut, const type & value) { streamOut.underlying_stream() << value; #ifndef NDEBUG streamOut.recalculate_string(); #endif return streamOut; } } template< class type> inline typename Private::return_from_write_to_stream< type>::return_type operator<< ( const str_stream & streamOut, const type & value) { return Private::write_to_stream( streamOut, value) ; } // allow function IO manipulators inline const str_stream & operator<< ( const str_stream & streamOut, std::ios_base & (*func)( std::ios_base&) ) { func( streamOut.underlying_stream()); return streamOut; } inline const str_stream & operator<< ( const str_stream & streamOut, std::basic_ios< char> & (*func)( std::basic_ios< char> &) ) { func( streamOut.underlying_stream()); return streamOut; } inline const str_stream & operator<< ( const str_stream & streamOut, std::ostream & (*func)( std::ostream &) ) { func( streamOut.underlying_stream()); return streamOut; } // END OF - allow function IO manipulators int main() { int nUsersCount = 45; std::string s = "There have been "; s += str_stream( nUsersCount) << " users logged on so far"; std::cout << s << std::endl; // or, you can do this: s = "There have been "; s += str_stream( nUsersCount); s += " users logged on so far"; std::cout << s << std::endl; std::cin.get(); return 0; } |