Listing K
#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;
}