Streams cannot be passed by value, so a reference to the same stream passed as argument is returned. This is simply a convenience.
For example, suppose you have a 2D cartesian point class with the usual constructors:
1 2 3 4 5 6 7
|
template <typename T>
struct point
{
T x, y;
point(): x(), y() { }
point( T x, T y ): x(x), y(y) { }
};
|
1 2 3
|
int main()
{
point<int> p (10,-2);
|
At some junction, you will probably want to be able to print that point. What you'd like to see is:
(10,-2)
So you write a function that knows how to print a point:
1 2 3 4 5
|
template <typename T>
void print( const point <T> & p )
{
std::cout << "(" << p.x << "," << p.y << ")";
}
|
A little later you realize it would be very convenient to be able to print that point to
any output stream. You modify your function:
1 2 3 4 5
|
template <typename T>
void print( std::ostream& outs, const point <T> & p )
{
outs << "(" << p.x << "," << p.y << ")";
}
|
1 2 3
|
std::cerr << "Sorry, the point ";
print( std::cerr, p );
std::cerr << " is invalid.\n";
|
What would be really nice, of course, is to be able to chain all those statements together into one line. For that, we'd need to have the function return a stream to work with:
1 2 3 4 5
|
template <typename T>
std::ostream& print( std::ostream& outs, const point <T> & p )
{
return outs << "(" << p.x << "," << p.y << ")";
}
|
|
std::cerr << "Sorry, the point "; print( std::cerr, p ) << " is invalid.\n";
|
Well -- technically, that's still two statements. We can make it one:
|
print( std::cerr << "Sorry, the point ", p ) << " is invalid.\n";
|
Notice that at this point we are exactly one step off from an insertion operator:
1 2 3 4 5
|
template <typename T>
std::ostream& operator << ( std::ostream& outs, const point <T> & p )
{
return outs << "(" << p.x << "," << p.y << ")";
}
|
|
std::cerr << "Sorry, the point " << p << " is invalid.\n";
|
That last line of code is automagically converted by the compiler into a function call exactly like our last
print() example above.
The utility of the reference, then, is to allow you to chain a series of function calls using the same stream as argument.
Hope this helps.