Step 3 of 5
Printing with operator<<
std::cout << x works for built-in types because the standard library defines operator<< for each of them. You can add one for your own types, and then they print like anything else, including into files and string streams.
#include <iostream>
#include <sstream>
#include <string>
struct Date {
int y, m, d;
};
std::ostream& operator<<(std::ostream& os, const Date& date) {
os << date.y << "-";
if (date.m < 10) os << "0";
os << date.m << "-";
if (date.d < 10) os << "0";
return os << date.d;
}
int main() {
Date launch{1969, 7, 20};
std::cout << "launch: " << launch << "\n";
std::ostringstream text;
text << launch;
std::string s = text.str();
std::cout << s.size() << " chars\n";
}
launch: 1969-07-20
10 chars
The required shape
std::ostream& operator<<(std::ostream& os, const T& value)
- The left operand is the stream, so this must be a free function (you can't add members to
std::ostream). - Take the value by
const&: printing shouldn't copy or change it. - Return the stream by reference. That's what makes chaining work:
std::cout << "launch: " << launch << "\n"is evaluated as((std::cout << "launch: ") << launch) << "\n", so each<<needs the stream back from the previous one.
Because it takes any std::ostream, the same operator writes to std::cout, to a file (std::ofstream), or to a string (std::ostringstream), as the example shows.
Don't print a trailing newline inside operator<<; let the caller decide.
Your turn: make Score printable as T 13 - 7 CT.