I have written operator<<(ostream& os,…) methods for a few of the PAL types, to make it easy to output info about them (for debugging, esp.).
However, I've noticed one "feature" of operator<< that's causing behavior I don't want: it's binding uses the static type of the second parameter (the PAL object). This is not what I want since I want it to print out the full info about an object based on its run-time type.
I've seen some projects use operator>> for output, but then you have to write stuff like "myPalBody >> std::cout;", which seems weird and doesn't compose if you want to output it in the midst of other stuff.
I think it would be nice to define a new class along these lines:
Then PAL classes could extend Stringable and define a toString method that would be dispatched dynamically. And operator<< would also work dynamically for these types since it uses toString.
I thought I'd post to the list in case someone had an objection or an idea for improvement.
- Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Actually, what I think is better than making a base class to implement, is to just put all of the operator << methods in one header. The compiler can figure out what types go to what. You don't have to make them friend functions.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Actually, what I think is better than making a base class to implement, is to just put all of the operator methods in one header. The compiler can figure out what types go to what.
I'm not at all attached to putting the methods any particular place.
However, using operator<< isn't a solution for my problem, because I want to get the string version of the object based on its run-time type, not it's compile-time type, and the compiler can't figure out what types go to what at runtime.
You don't have to make them friend functions.
With the Stringable pattern, you're right, operator<< doesn't need to be a friend.
(Without a Stringable pattern, I think that if the classes are well-abstracted, it's pretty likely that at least some of them will contain data that would be nice to stringify but which will be inaccessible to non-friend/method code. However, since non-methods won't solve my problem, anyway, I don't think the friend vs. non-friend issue matters.)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You could just make an operator<< in a header that just calls toString on whatever it gets, but if you just include it as iosfwd, it's fine.
The reason I don't want ostream included in a header is that including ostream includes many thousands of lines of code. In that case, you would end up including ostream in every file of a system that uses pal, and the build time will go way up.
iosfwd just adds the declarations so that you can just include ostream in the cpp file where you implement the method, and build time won't suffer.
string is another offender, but stringfwd is not in the standard, and we end up with it all the time anyway. g++ has stringfwd, but not VC++. I hope c++0x has stringfwd.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You could just make an operator<< in a header that just calls toString on whatever it gets, but if you just include it as iosfwd, it's fine.
Do you mean with or without a base class they inherit from like Stringable? Sorry if I'm being dense, but I don't see how it would work unless they all have a common base class.
The reason I don't want ostream included in a header is that including ostream includes many thousands of lines of code. In that case, you would end up including ostream in every file of a system that uses pal, and the build time will go way up.
iosfwd just adds the declarations so that you can just include ostream in the cpp file where you implement the method, and build time won't suffer.
Wow, I had no idea ostream was so heavyweight. iosfwd sounds like a good idea to me.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have written operator<<(ostream& os,…) methods for a few of the PAL types, to make it easy to output info about them (for debugging, esp.).
However, I've noticed one "feature" of operator<< that's causing behavior I don't want: it's binding uses the static type of the second parameter (the PAL object). This is not what I want since I want it to print out the full info about an object based on its run-time type.
I've seen some projects use operator>> for output, but then you have to write stuff like "myPalBody >> std::cout;", which seems weird and doesn't compose if you want to output it in the midst of other stuff.
I think it would be nice to define a new class along these lines:
Then PAL classes could extend Stringable and define a toString method that would be dispatched dynamically. And operator<< would also work dynamically for these types since it uses toString.
I thought I'd post to the list in case someone had an objection or an idea for improvement.
- Chris
May I request that you don't inline it, and only include <iosfwd> in the header so we don't end up including ostream everywhere?
Actually, what I think is better than making a base class to implement, is to just put all of the operator << methods in one header. The compiler can figure out what types go to what. You don't have to make them friend functions.
Sure, that's no problem. I didn't know about the iosfwd header. I'm curious, though, why? What's the big deal about including ostream?
I'm not at all attached to putting the methods any particular place.
However, using operator<< isn't a solution for my problem, because I want to get the string version of the object based on its run-time type, not it's compile-time type, and the compiler can't figure out what types go to what at runtime.
With the Stringable pattern, you're right, operator<< doesn't need to be a friend.
(Without a Stringable pattern, I think that if the classes are well-abstracted, it's pretty likely that at least some of them will contain data that would be nice to stringify but which will be inaccessible to non-friend/method code. However, since non-methods won't solve my problem, anyway, I don't think the friend vs. non-friend issue matters.)
You could just make an operator<< in a header that just calls toString on whatever it gets, but if you just include it as iosfwd, it's fine.
The reason I don't want ostream included in a header is that including ostream includes many thousands of lines of code. In that case, you would end up including ostream in every file of a system that uses pal, and the build time will go way up.
iosfwd just adds the declarations so that you can just include ostream in the cpp file where you implement the method, and build time won't suffer.
string is another offender, but stringfwd is not in the standard, and we end up with it all the time anyway. g++ has stringfwd, but not VC++. I hope c++0x has stringfwd.
Do you mean with or without a base class they inherit from like Stringable? Sorry if I'm being dense, but I don't see how it would work unless they all have a common base class.
iosfwd just adds the declarations so that you can just include ostream in the cpp file where you implement the method, and build time won't suffer.
Wow, I had no idea ostream was so heavyweight. iosfwd sounds like a good idea to me.