liveBook · Manning

Stream insertion operator

As explained in 100 C++ Mistakes and How to Avoid Them

The stream insertion operator, written operator<< in C++, is an overloaded operator used to write formatted values to an output stream such as std::ostream.

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

How 100 C++ Mistakes and How to Avoid Them covers it

How deep it goes
Explains chained output and class overloads through code, but defers detailed overload-resolution and stream internals.
Examples
Demonstrates std::cout chains, istringstream extraction, octal input, Rational output, and Date formatting.
What it assumes
Assumes basic C++ types, classes, streams, and operator syntax while teaching typed conversion checks from concrete examples.
What you can do after
Apply stream insertion to produce readable typed output and design natural output syntax for user-defined classes.
How it connects
Connects stream insertion with formatted I/O, operator overloading, friend functions, class invariants, and encapsulation.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 C++ Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.