The stream insertion operator, written operator<<, writes formatted values to an output stream such as std::ostream. It replaces brittle printf-style formatting with typed, chained output. section 6.1
Use the operator to make output clearer and more consistent:
- Chain values naturally: std::cout << pi << " being eaten by " << cats << " cats". section 6.1
- Prefer stream operations when format strings would obscure which conversion failed or make maintenance difficult. section 6.1
- Overload operator<< for a class when its values should print like built-in data types; keep the operation intuitive and non-mutating. section 7.4 section 9.12
Typed parsing and readable output
A string stream can extract values one at a time with str >> pi, str >> cats, and str >> buffer, checking fail() after each operation. The resulting values can then be written with std::cout << pi << " being eaten by " << cats. For class values, a Rational or Date overload lets clients write std::cout << value instead of calling a special print method. section 6.1 section 7.4 section 9.12
Listing 7.4 An implementation that provides intuitive use
class Rational {
private:
int num;
int den;
static int gcd(int a, int b) { return a == 0 ? b : gcd(b % a, a); }
void reduce();
int validate(int v) {
return v != 0 ? v : throw
std::invalid_argument("zero denominator");
}
public:
Rational(int n, int d=1) : num(n), den(validate(d)) { reduce(); }
Rational operator+(const Rational& o) const;
Rational operator*(const Rational& o) const;
friend std::ostream& operator<<(std::ostream&, const Rational&);
};
void Rational::reduce() {
int div = gcd(num, den);
num = (den > 0 ? 1 : -1) * num / div;
den = abs(den) / div;
}
Rational Rational::operator+(const Rational& o) const { #1
return Rational(num * o.den + den * o.num, den * o.den);
}
Rational Rational::operator*(const Rational& o) const { #2
return Rational(num * o.num, den * o.den);
}
std::ostream& operator<<(std::ostream& out, const Rational& r) { #3
out << r.num << '/' << r.den;
return out;
}
int main() {
Rational r1(1, 3);
Rational r2(2, 4);
std::cout << r1 + r2 << '\n';
//Rational(1, 0);
return 0;
}
Inspect the Rational implementation to see operator<< placed alongside arithmetic overloads and used as a standard output operation. section 7.4
