views:

271

answers:

5

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.

+3  A: 

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

anon
+1  A: 

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.

RaphaelSP
I would do something like this too. Except I would return a reference to `MyClass` instead of `ostringstream`.
Matt Price
This template will not match manipulators (std::endl, std::hex...) those have to be handled with non-templated overloads.
David Rodríguez - dribeas
@Matt: indeed, it would make it more versatile; @dribeas: Ooh, I've learnt something today. I'd recommend your answer to the question you linked to.
RaphaelSP
+1  A: 

I really liked the answer to question kind of simmilar yours, namely std::endl is of unknown type when overloading operator<<

Oleg Zhylin
I think they may be aware of that one...
Troubadour
that was my question, lol
Kazoom
@Kazoom: This is not helping anyone. Repeating the same question or slightly different question that were already answered on a previous question diludes the information. If you need clarifying, go back to one of the original questions and request more help.
David Rodríguez - dribeas
+2  A: 

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.

Troubadour
A: 

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.

AProgrammer