0
votes

I found this question on archived file at joelonsoftware.com http://discuss.joelonsoftware.com/default.asp?joel.3.594503.11

"Hi,

I'm having a particularly slow day and can't get my head round an operator overloading problem. I would like a class to be able to accept data via an insertation operator, i.e:

myClassInstance << std::string("a string") << 4 << 3.4 << std::endl;

Internally, I'd like everything to end up in a stringstream so I can then farm it off to other streams (say std::cout and an ofstream). I have got horribly confused how I can do this without having to write an operator<< overload for every data type, and how an input stream would be created on the first call (myClassInstance << ...).

Any help gratefully received!"

This is exactly what I am trying to do. I have found my way to deal with all types by defining templates and another overloaded method to deal with manipulators like endl defined in ostream class.

UIStream&  UIStream ::operator << (const T str)
 {
     CString cstr(stringify(str).c_str());
     theFrame->m_pOutputView->WriteMessage(cstr);
     return *this;
 }

 //for manipulators like std::endl
UIStream&  UIStream ::operator <<(ostream& (*m)(ostream&))
{
     //stream<<*m; 
     //CString cstr((*m)(new ostream).c_str());
    if(*m==&std::endl);
        theFrame->m_pOutputView->WriteMessage("\n");
     return (*this);
}

I am still struggling with manipulators that take arguments like hex dec or oct this are defined in ios_base.

4
I really liked the answer to question kind of simmilar yours, namely std::endl is of unknown type when overloading operator<<Oleg Zhylin
This has been dealt with in already two posts by the same user. Please, Kazoom, read the answers!David Rodríguez - dribeas
Are you sure? I thought the question related to dealing with manipulators that take arguments, something not covered by the other questions as far as I can see. Although in saying that hex, dec and oct are not manipulators that take arguments...Troubadour
This question has already been answered before (among others in an answer of mine here: stackoverflow.com/questions/1133739/…)David Rodríguez - dribeas

4 Answers

3
votes

Probably an idea to read a good book on the topic. I recommend Standard C++ IOStreams and Locales by Langer and Kreft.

2
votes

To make your stream work with manipulators that take arguments is not quite as straightforward as when they do not have arguments. The problem is that the maniuplator will be of the form

ImpDefClass manipulator( argument list );

where ImpDefClass is, as its name suggests, an implementation defined class. For example, on my system, setprecision is declared as

inline _Setprecision setprecision(int __n);

where _Setprecision is just a struct that my implementation defines itself.

The problem therefore is that you can't just write a new stream operator like

UIStream& operator<<( UIStream&, XXX );

because XXX is the implementation defined class. I'm not sure how to get around that other than define your own manipulators to perform the same tasks or hardwire your code to specific implementations.

1
votes

The way I would go is just to include a std::stringstream in MyClass, and overload << to take a MyClass as lhs and anything as RHS.

class MyClass {
public:
   template <class T>
   MyClass & operator <<(const T & rhs) {
       m_stream << rhs;
       return *this;
    }
    private:
        std::ostringstream m_stream;
};

edit: I guess it's not exactly what you are looking for. Still could be useful for simpler uses.

0
votes

The more questions you ask, the more I'm convinced that the correct approach to your problem is writing a new streambuf. There is documentation for that on the net -- explaining it here would be a little too long for me -- and there is a library of boost called iostreams which can help you.