I just came across this question which is about how to be able to print an object via
std::cout << x << std::endl;
As I understood, the standard way to accomplish this is to overload the ostreams << operator. However, this is adding a feature to the ostream rather than to my class.
The alternative (also given as answer to the above mentioned question) is to override the string conversion operator. However, this comes with the warning of leading to "unintentional conversions and hard-to-trace bugs".
Now i wonder if there are any drawbacks of writing a toString() method and then using it via
std::cout << x.toString() << std::endl;
Output streams handle output formatting as well as output. So with your toString() method clients won't be able to manage the formatting for the object the way they do for everything else:
// set specific formatting options for printing a value
std::cout << std::scientific << std::setprecision(10) << 10.0 << '\n'; // prints 1.0000000000e+01
// set formatting based on user's cultural conventions
std::cout.imbue(std::locale(""));
std::cout << 10000000 << '\n'; // depending on your system configuration may print "10,000,000"
Perhaps you don't care to allow any formatting so perhaps this won't matter.
Another consideration is that outputting to a stream doesn't require that the entire string representation be in memory at once, but your toString() method does.
Others have pointed this out, but I think a clearer way of saying it is that your classes interface is not limited to just the methods it provides, but also includes the other functions you build around it, including non-member functions such as the operator<< overloads you provide. Even though it's not a method of your class you should still think of it as part of your class's interface.
Here's an article that talks about this which perhaps you will find helpful: How Non-Member Functions Improve Encapsulation
Here's a simple example of overloading operator<< for a user defined class:
#include <iostream>
struct MyClass {
int n;
};
std::ostream &operator<< (std::ostream &os, MyClass const &m) {
for (int i = 0; i < m.n; ++i) {
os << i << ' ';
}
return os;
}
int main() {
MyClass c = {1000000};
std::cout << c << '\n';
}
As I understood, the standard way to accomplish this is to overload the ostreams << operator. However, this is adding a feature to the ostream rather than to my class.
And this is good thing. The smaller your class is the better. If popular C++ idiom allows you to have one more thing out of your class why not follow it?
Now i wonder if there are any drawbacks of writing a toString() method
The drawbacks are:
operator<< works in uniform way with builtin types (like int) and user-defined types. toString could be available for classes only
C++ is more heterogeneous than Java. std::string is the most popular string, but still there exist other string classes and they are used.
the string must be created, which potentially might come with a performance hit. If you write to stream directly you avoid it.
They are fundamentally different things. Providing a operator<< overload effectively extends the interface of the stream, making objects of your class type streamable. Providing a toString function extends the interface of your class, making it possible to get a std::string from your class. These represent different things.
The interface of your class should entirely correspond to what it represents in your program logic (single responsibility). Rarely is toString a natural part of a class's interface. However, extending the interface of the stream to accept more objects is much more logical.
That is, in one case you are saying "Now you can stream objects of this class type". In the other case you are saying "You can turn objects of this class type into a std::string." - it just so happens that that std::string is then streamable. Think about it - does it really make sense for my Person class to have a toString function? Since when have I been able to turn people into text?
Your first assumption is wrong. You don't need to make any changes in ostream.
An operator method like operator<< can be defined in two ways: As a method of the ostream class, taking your x object as a parameter, or as a plain old function with two parameters, taking an ostream as the first parameter, and your x object as the second parameter.
There is nothing wrong with a toString() function per class. It has the advantages of being more explicit, it can be made polymorph and it can be used in other situations than streaming, but you need to have a coding rule when working with a team ("was it to_string(), or str(), or streaming()?").
Overloading operator<< is more idiomatic. It just takes ostream as parameter and makes the conversion implicit when streaming, but since this is idiomatic in C++, most will expect an overloaded operator<< when seeing std::cout << x;.
Related
I would like to perform some specialized processing of the data written to a std::ostream as it is being written. Lets say (for simplicity's sake), every time any of the basic data types are injected to my ostream, I want a comma to follow the injection.
template<class T>
class MyOstream : public T
{
// Impossible code
};
#include <sstream>
using namespace std;
int main()
{
int i = -2;
double d = 3.21;
char[] s = "char array";
bool b = false;
MyOstream<ostringstream> mos;
mos << i << d << s << b;
cout << mos.str() << endl;
return 0;
}
and I want the output to be:
-2,3.21,char array,0,
As I recall, the only virtual method defined for std::ostream is the destructor, so the normal approach of method overrides is out of the question. But would it be possible to achieve this behavior by using a specialized streambuf? streambufs DO have several virtual methods. I know there are virtual methods used to update pointers as data is written, but I don't yet fully understand all of these methods. I was hoping someone could tell me if perhaps one of these methods is called exactly once with each such injection and thus give me a way to do my magic. But if, for example, a large character array (that exceeds the buffer size) results in several calls to that same method (to move data through the streambuf in chunks), then I'm sunk.
The only other alternative I have is to wrap the ostream instead of inheriting from it. This is easy enough, but such an approach precludes the possibility of passing the ostream to a third-party print routine (that expects a std::ostream).
Yes, I know what I'm contemplating is pure evil.
std::string (as most — if not all — standard classes) doesn’t have any virtual methods, so creating an inherited class with virtual methods will result in UB (due most likely to the destructor). (correct me if I am wrong).
I thought that inheriting without polymorphism it’s ok though, until I read upon the net on this subject.
For instance, in this answer: Why should one not derive from c++ std string class? some arguments are given against this practice. The main reason seems to be the slicing problem which will inhibit the added functionality when the derived object is passed to a function in place of a std::string parameter, thus making the non-polymorphism not logical. The idiomatic C++ way is to create free functions if one wants to extend the functionality of string. And I agree with all that, especially since I am an advocate for free functions instead of monolithic classes.
That being said I think that I found a situation that I think actually warrants the non-polymorphic inheritance from std::string. I will first show what issue I am trying to solve, then I will show the reasons why I think inheriting from std::string is the best solution here.
When porting a function used for debugging purposes from C to C++ I realised there is no way to create formatted strings in C++ (not using C-like string functions e.g. sprintf). I.e.:
C version: void someKindOfError(const char *format, ...);
this would be called like:
someKindOfError("invalid argument %d, size = %d", i, size);
C++ version: void someKindOfError(const std::string &message);
to call this to a similar effect would be:
std::stringstream ss;
ss << "invalid argument " << i << ", size = " << size;
someKindOfError(ss.str());
this can’t be a one liner because the << operator returns an ostream. So this requires 2 extra lines and an extra variable.
The solution I came up with is a class called StreamString that inherits from std::string (actually a templated BasicStreamString that inherits from basic_string<>, but that’t not important) and as far as the new functionality goes it has the operator << that mimics the behaviour of the stringstream operator and conversion to and from string.
So the previous example can become:
someKindOfError(StreamString() << "invalid argument " << i << ", size = " << size);
remember that the parameter type is still const std::string &
The class is created and fully functional. And I found this class very useful in a lot of places when a string is need to be created ad-hoc, without the extra burden of having to declare an extra stringstream variable. And this object can be manipulated further like a stringstream, but it is actually a string and can be passed to functions expecting string.
Why I think this is an exception to the C++ idiom:
the object needs to behave exactly like a string when passed to functions expecting a string, so the slicing problem is not an issue.
the only (noteworthy) added functionality is the operator << which I am reluctant to overload as a free function for a standard string object (this would be done in a library).
One alternative I can think of is to create a variadic templated free function. Something like:
template <class... Args>
std::string createString(Args... args);
which allow us to call like this:
someKindOfError(createString("invalid argument ", i , ", size = " , size));
One disadvantage of this alternative is the lost of the ability to easily manipulate the string like an stringstream after it’s creation. But I suppose I can create a free function to handle that too. Also people are use with the operator << to perform formatted inserts.
To round up:
Is my solution bad practice (or worst) or it is an exception to the C++ idiom and it is OK?
If it is bad, what viable alternatives are there? Is createString ok? Can it be improved?
You don't need to derive a class from std::string for this. Just create an unrelated class, say StringBuilder that keeps a std::stringstream internally. Overload operator << for this class and add a std::string cast operator.
Something like this should do the trick (untested):
class StringBuilder
{
std::ostringstream oss;
public:
operator std::string() const
{
return oss.str();
}
template <class T>
friend StringBuilder& operator <<(StringBuilder& sb, const T& t)
{
sb.oss << t;
return *this;
}
};
Your StreamString class is OK, in that there do not seem to be any situations where normal usage of it could get you into trouble. Even so, there are a lot of alternatives that might be more appropriate to this situation.
Use a pre-existing library, such as Boost.Format, rather than rolling your own. This has the advantage of being widely known, tested, supported, etc...
Write someKindOfError to be a variadic template, to match the C version, but with added C++ type-safety goodness. This has the advantage of matching the C version, and so being familiar to your existing users.
Give StringStream a conversion operator or an explicit to_string function, rather than inheriting from std::string. This gives you more flexibility to change the implementation of the StringStream at a later stage. (For example, at a later stage, you might decide that you want to use some kind of cacheing or buffering scheme, but this would be impossible if you do not know exactly when the final string will be extracted from the StringStream).
As it is, your design is conceptually flawed. The only thing that you need is the ability to convert a StringStream to a std::string. Inheritance is an overly heavy-handed way of achieving that goal, when compared to using a conversion operator.
Write your original stringstream code as a one-liner:
someKindOfError(static_cast<std::stringstream &>(
std::stringstream{} << "invalid argument " << i << ", size = " << size).str());
... well, that's pretty ugly, so maybe not. You should consider it though, if your only reason for not doing this was that you thought it was not possible.
What is the main purpose of overloading operators in C++?
In the code below, << and >> are overloaded; what is the advantage to doing so?
#include <iostream>
#include <string>
using namespace std;
class book {
string name,gvari;
double cost;
int year;
public:
book(){};
book(string a, string b, double c, int d) { a=name;b=gvari;c=cost;d=year; }
~book() {}
double setprice(double a) { return a=cost; }
friend ostream& operator <<(ostream& , book&);
void printbook(){
cout<<"wignis saxeli "<<name<<endl;
cout<<"wignis avtori "<<gvari<<endl;
cout<<"girebuleba "<<cost<<endl;
cout<<"weli "<<year<<endl;
}
};
ostream& operator <<(ostream& out, book& a){
out<<"wignis saxeli "<<a.name<<endl;
out<<"wignis avtori "<<a.gvari<<endl;
out<<"girebuleba "<<a.cost<<endl;
out<<"weli "<<a.year<<endl;
return out;
}
class library_card : public book {
string nomeri;
int raod;
public:
library_card(){};
library_card( string a, int b){a=nomeri;b=raod;}
~library_card() {};
void printcard(){
cout<<"katalogis nomeri "<<nomeri<<endl;
cout<<"gacemis raodenoba "<<raod<<endl;
}
friend ostream& operator <<(ostream& , library_card&);
};
ostream& operator <<(ostream& out, library_card& b) {
out<<"katalogis nomeri "<<b.nomeri<<endl;
out<<"gacemis raodenoba "<<b.raod<<endl;
return out;
}
int main() {
book A("robizon kruno","giorgi",15,1992);
library_card B("910CPP",123);
A.printbook();
B.printbook();
A.setprice(15);
B.printbook();
system("pause");
return 0;
}
It doesn't ever have to be used; it's just a convenience, a way of letting user-defined types act more like built-in types.
For example, if you overload operator<<, you can stream books the same way as integers and strings:
cout << "Book #" << n << " is " << books[n] << endl;
If you don't, you'd have to write the same thing like this:
cout << "Book #" << n << " is ";
books[n].printbook();
cout << endl;
Similarly, if you create a Fraction class and give it an operator+, you can use fractions the same way you use integers, and so on.
It's sometimes a tough design choice whether your class should act like a native type in one way or another (for example, does string's operator+ make sense?), but the point is that C++ gives you the choice.
Overloading the << operator allows your objects to be written out to the output in a way you specify, when passed to cout.
Otherwise, cout would just write out the address to your object.
The purpose of overloading operators is mostly syntactic sugar. It makes ugly stuff look nice.
But it's also about unifying interfaces, and an important reason for unifying interfaces is polymoprphism, in this case especially with templates.
Imagine we have a lovely complex number class Complex, and we want to have a Taylor series approximation of sine that we want to make work for Complex and double types.
If we support operator overloading on *, =, / etc. then we can write it like this:
template<typename T>
T sin(T t)
{
T t2 = t*t;
return t*(1 - t2/6 + (t2*t2)/120 );
}
If we cant have overloading on *, / etc. then it starts to get ugly, as we need a helper class to unify the interface for doubles and Complex, heres what it might look like. (I'm still allowing overloading of operator=, otherwise it gets even worse).
template<typename T>
T sin(T t)
{
T t2 = helper<T>::mult( t, t );
T t4 = helper<T>::mult( t2, t2 );
T s(1);
helper<T>::sincrement( &s, -1./6, t2);
helper<T>::sincrement( &s, -1./120, t4);
return helper<T>::mult( t, s );
}
template<>
struct helper<double>
{
static double mult( double a, double b) { return a*b; }
static void sincrement( double * v, double s, double x) { *v += s*x; }
}
template<>
struct helper<Complex>
{
static Complex mult( Complex a, Complex b ) { return a.mult(b); }
static void sincrement( Complex * v, double s, Complex x ) { v->add( x.scale(s) ); }
}
Now I know operator overloading can be ugly, and can hide what's really happening, but used correctly I think that it makes cases like this much easier to understand.
Overloading operators allows a special case of polymorphism.
The best example I can think of is a string class with the + operator overloaded.
In this case the operator would be overloaded to concatenate strings instead of "adding" two strings which doesn't make any sense.
To answer your question specifically overloading operators can (in some cases) produce more readable and maintainable code. However, what "makes sense" for one person may not make sense for the person maintaining the code.
You could easily use a member function instead, it just provides a "syntactic sugar" in most cases. For example in some languages adding 2 strings does a concat.
stringOne = stringOne + stringTwo;
Though it could easily be implemented with a member function like
stringOne.concat(stringTwo);
With an overloaded operator, you can use standard library algorithms which require that operator to be overloaded.
For example:
struct wtf{ wtf(int omg): omg(omg){} int omg; };
wtf operator+ (wtf const &omg, wtf const &lol)
{
return wtf(omg.omg+ lol.omg);
}
#include <iostream>
#include <numeric>
int main()
{
wtf lol[3]= { wtf(1), wtf(2), wtf(3) };
std::cout<< std::accumulate(lol, lol+ 3, wtf(0)).omg;
}
6
The thing about C++ is it passes objects by value, as a fundamental aim of how it works, and this really greatly changes how objects work compared to reference-semantics oriented languages like Java and Objective-C.
Whereas in one of those languages there is a clear distinction between primitive types and objects in terms of how you use them - that is, you copy primitives a lot, you stick them into expressions involving operators, that sort of thing, whereas your interaction with objects is mainly instantiating them, calling methods on them and passing the references to them into functions - in C++ you can use objects pretty much the same way as you use primitives. This brings up a lot of complicated issues that C++ programmers have to deal with, like object lifetimes, whether an object is an lvalue or rvalue (that is, if it has a lifetime outside the expression it appears in), etc.
One thing your question brings up is why a class would overload << and >>. The C++ standard library uses this convention for iostream classes, and highlights another big difference from reference-semantics based languages - in a value-semantics oriented language, class inheritance is inadequate to fully describe what you want to do with an object. We can loosely say that if an object overloads << and >> to stream data in and out of some resource, then it satisfies the concept of an iostream, even if it doesn't inherit from iostream, or ios_base, or something. The meaning of this is twofold:
If you put a value of this type into an expression and used <<, it would behave as expected.
If you instantiate a template with this type as a parameter, which calls operator<< on the object, the code will compile successfully.
I deliberately used the word concept above because there was going to be a feature in C++11 (it got postponed to the next version) called Concepts which would formalise this idea in the language. The situation we have now is a sort of duck typing - if a template wants to use a certain operator with a type, it will compile if the type provides that operator and won't if it doesn't, regardless of what the operator actually means. operator<< is a case in point - in its original meaning, for an integer type, it means "leftward signed bit-shift", but when you are using the concept of iostream, it means "stream data from the object on the right into the object to the left".
Your main purpose overloading the << and >> operators is to create an API in the spirit of the C++ standard library, so it becomes more natural for experienced C++ programmers to use your types.
It's so this way that the operators << and >> are known as insertion/extraction operators when used with the STL streams. From C they were just bit shift operators.
Since in the realm of standard C++ they acquired that meaning and even received new nomenclatures for that, It's aways good to reuse already established programming jargon.
Now, originally in the C++ creation, why it has gone this way for stream operations? by getting the shift operators and labeling them as insertion and extraction operators, I don't know, maybe a matter of taste to better express the idea of insertion/extraction given the appearance of the shift operators, a meaning which now, has become standard and suits to be reused.
Background
I have a container class which uses vector<std::string> internally. I have provided a method AddChar(std::string) to this wrapper class which does a push_back() to the internal vector. In my code, I have to add multiple items to the container some time. For that I have to use
container.AddChar("First");
container.AddChar("Second");
This makes the code larger. So to make it more easier, I plan to overload operator <<. So that I can write
container << "First" << "Second"
and two items will get added to underlying vector.
Here is the code I used for that
class ExtendedVector
{
private:
vector<string> container;
public:
friend ExtendedVector& operator<<(ExtendedVector& cont,const std::string str){
cont.AddChar(str);
return cont;
}
void AddChar(const std::string str)
{
container.push_back(str);
}
string ToString()
{
string output;
vector<string>::iterator it = container.begin();
while(it != container.end())
{
output += *it;
++it;
}
return output;
}
};
It is working as expected.
Questions
Is operator overload written correctly?
Is it a good practice to overload operators in situations like this?
Will there be any performance issues or any other issues with this code?
Any thoughts?
Edit
After hearing the excellent comments, I decided not to overload << as it doesn't make sense here. I removed the operator overload code and here is the final code.
class ExtendedVector
{
private:
vector<string> container;
public:
ExtendedVector& AddChar(const std::string str)
{
container.push_back(str);
return *this;
}
.. other methods
}
This allows me to add
container.AddChar("First").AddChar("Second")
In C#, I can do this more easily by using the params keyword. Code will be like
void AddChar(params string[] str)
{
foreach(string s in str)
// add to the underlying collection
}
I know in C++, we can use ... to specify variable langth of parameters. But AFAIK, it is not type safe. So is it a recommended practice to do so? So that I can write
container.AddChar("First","Second")
Thanks for the replies.
Is operator overload written correctly?
It is, but one can do better. Like someone else mentioned, your function can be defined entirely out of existing, public functions. Why not make it use only those? Right now, it is a friend, which means it belongs to the implementation details. The same is true if you put operator<< as a member into your class. However, make your operator<< a non-member, non-friend function.
class ExtendedVector {
...
};
// note, now it is *entirely decoupled* from any private members!
ExtendedVector& operator<<(ExtendedVector& cont, const std::string& str){
cont.AddChar(str);
return cont;
}
If you change your class, you will not be sure that that your operator<< will still work. But if your operator<< entirely depends only on public functions, then you can be sure that it will work after changes were made to implementation details of your class only. Yay!
Is it a good practice to overload operators in situations like this?
As another guy said again, this is arguable. In many situations, operator overloading will look "neat" at first sight, but will look like hell next year, because you have no clue anymore what you had in mind when giving some symbols special love. In the case of operator<<, i think this is an OK use. Its use as an insertion operator for streams is well known. And i know of Qt and KDE applications that use it extensively in cases like
QStringList items;
items << "item1" << "item2";
A similar case is boost.format which also reuses operator% for passing arguments for placeholders in its string:
format("hello %1%, i'm %2% y'old") % "benny" % 21
It's of course also arguable to use it there. But its use for printf format specifies are well known and so its use is OK there too, imho. But as always, style is also subjective so take it with a grain of salt :)
How can i accept variable length arguments in a typesafe way?
Well, there is the way of accepting a vector if you are looking for homogeneous arguments:
void AddChars(std::vector<std::string> const& v) {
std::vector<std::string>::const_iterator cit =
v.begin();
for(;cit != v.begin(); ++cit) {
AddChar(*cit);
}
}
It's not really confortable to pass it though. You have to construct your vector manually and then pass... I see you already have the right feeling about the vararg style functions. One should not use them for this kind of code and only when interfacing with C code or debugging functions if at all. Another way to handle this case is to apply preprocessor programming. This is an advanced topic and is quite hacky. The idea is to automatically generate overloads up to some upper limit roughly like this:
#define GEN_OVERLOAD(X) \
void AddChars(GEN_ARGS(X, std::string arg)) { \
/* now access arg0 ... arg(X-1) */ \
/* AddChar(arg0); ... AddChar(arg(N-1)); */ \
GEN_PRINT_ARG1(X, AddChar, arg) \
}
/* call macro with 0, 1, ..., 9 as argument
GEN_PRINT(10, GEN_OVERLOAD)
That is pseudo code. You can have a look at the boost preprocessor library here.
Next C++ version will offer far better possibilities. Initializer lists can be used:
void AddChars(initializer_list<std::string> ilist) {
// range based for loop
for(std::string const& s : ilist) {
AddChar(s);
}
}
...
AddChars({"hello", "you", "this is fun"});
It's also possible in next C++ to support arbitrary many (mixed-type) arguments using variadic templates. GCC4.4 will have support for them. GCC 4.3 already partially supports them.
1) Yes, except since AddChar is public there's no reason it needs to be a friend.
2) This is arguable. << is sort of in the position of being the operator whose overloading for "weird" things is at least grudgingly accepted.
3) Nothing obvious. As always, profiling is your friend. You may want to consider passing the string parameters to AddChar and operator<< by const reference (const std::string&) to avoid unnecessary copying.
Is it a good practice to overload
operators in situations like this?
I don't think so. It's confusing as hell for someone who doesn't know that you've overloaded the operator. Just stick to descriptive method names and forget about the extra characters you're typing, its just not worth it. Your maintainer (or you yourself in 6 months) will thank you.
I'd prefer not to overload it that way personally because vectors don't normally have an overloaded left shift operator - it's not really it's idiom ;-)
I'd probably return a reference from AddChar instead like so:
ExtendedVector& AddChar(const std::string& str) {
container.push_back(str);
return *this;
}
so you can then do
container.AddChar("First").AddChar("Second");
which isn't really much bigger than bitshift operators.
(also see Logan's comment about passing strings in by reference instead of by value).
The operator overloading in this case is not good practice as it makes the code less readable. The standard std::vector doesn't have it either for pushing elements, for good reasons.
If you're worried about the caller code being too long, you could consider this instead of the overloaded operator:
container.AddChar("First").AddChar("Second");
This will be possible if you have AddChar() return *this.
It's funny that you have this toString() function. In that case, an operator<< to output to a stream would be the standard thing to use instead! So if you want to use operators make the toString() function an operator<<.
The operator is not correctly overloaded here. There is no reason to make the operator a friend since it can be a member of the class. Friend is for functions which are not actual members of the class (such as when overloading << for ostream so the object can be output to cout or ofstreams).
What you actually want the operator to be:
ExtendedVector& operator<<(const std::string str){
AddChar(str);
return *this;
}
It is usually considered bad practice to overload operators in a way that has them do something than they do normally. << is normally bit shift, so overloading it this way can be confusing. Obviously STL overloads << for "stream insertion" and so along with that it might make sense to overload it for your use in a similar way. But that doesn't seem like what you're doing, so you probably want to avoid it.
There are no performance issues since operator overloading is the same as a regular function call, just the call is hidden because it is done automatically by the compiler.
This is going to make things rather confusing, I would use the same syntax as std::cin into a variable:
std::cin >> someint;
"First" >> container;
This way it is at least an insertion operator. To me when anything has a << overloaded operator I expect it to be outputting something. Just like std::cout.
The question could be subjective, so the syntax of
std::ostream& operator << (std::ostream & o, const SomeClass &a) {
return o << a.accessor().. ;
}
When do you normally define this for the classes that you write, when do you avoid writing this friend function for your class.
IF I want to stream a class I normally write this:
std::ostream& operator << (std::ostream& o, const SomeClass& a)
{
a.print(o);
return o;
}
Then make print a const method on SomeClass that knows how to serialize the class to a stream.
I would only overload operator<< when that has anything to do with streaming, or with shifting and the class is purely numeral. For writing something into an ostream, as in your code, i think it's fine. Anything else, i think, will cause confusion and i would better use member functions for those other purposes. One other application, which i think i would still do as an exception to the rule, is doing something like this:
StringList list;
list << "foo" << "bar" << "baz";
It is how Qt does it with its string list, and which i find quite nice.
A benefit of Martin's answer above is that you also get polymorphism for free. If you make print(ostream&) a virtual function, then the << operator acts like a virtual function as well!
As to when to overload the operator, do so anytime you think the class should be able to be written to a stream (file, socket, etc...). This might even be only for debug purposes. It is often useful to be able to output the internals of a class, so there is no real downside to overloading this operator.
I would consider using it for something like logging. So you can do:
SystemLog systemLog;
systemLog << "Processing Item #15";
systemLog << "Error 0014: Bad things happened.";
systemLog << system.executeCommand(cmd); // returns a result string
Or maybe for networking as in:
NetworkInterface networkInterface;
string message("Hello World! I'm a server.");
networkInterface << message;
Of course implementing these things as regular function is also possible and might just be preferable. Generally, you should beware of operator overloading. Only use it when it really fits.
I had never ever overloaded this one in production code. Although you might want do this if you log a lot, it'll be useful.
I implement this if, and only if, I intend to make use of that operator. This is pretty much never... my reasons for not implementing it are therefore not using it. If its for public use then include it for completeness, but certainly I wouldn't include this in every class in a project of your own, since for the most part you will not need to output a class to a stream. e.g. If you wrap your entry point in a class, providing this operator will be pointless.
I do it very frequently since it makes dumping the object to a log for debugging really convenient.