r.Print(out); // see how the bulk of the work is done by the 'Print()' method!

return out;

}

int main()

{

Rational r1(22, 7);

Rational r2(77, 17);

std::cout << "Rational = " << r1 << std::endl;

std::cout << "Call may also be chained due to the signature of the function: " << r1

<< " and " << r2 << std::endl;

return EXIT_SUCCESS;

}

```

%% Cell type:markdown id: tags:

Please notice the slightly weird expected syntax for the `operator<<`: the `std::ostream` appears actually twice; the reason for that is to enable chained calls:

Operator>> might be overloaded in a similar way; it might be used for instance to create an object from data readin a file. As usual with `operator>>`, you should be cautious and handle well the case in which the flux becomes invalid:

%% Cell type:code id: tags:

``` C++17

// Doesn't run on Xeus-cling due to definition of an operator outside of a class

// A ticket has been opened for this: https://github.com/QuantStack/xeus-cling/issues/214

#include <iostream>

class Rational

{

public :

explicit Rational(int numerator, int denominator);

void Print(std::ostream& out) const;

friend std::istream& operator>>(std::istream& in, Rational& r);

private:

//! Set method to modify numerator and denominator. I made the arbitrary choice to make it private

//! to illustrate friendship.

void Set(int numerator, int denominator);

private :

int numerator_ = 0;

int denominator_ = 0;

};

Rational::Rational(int numerator, int denominator)

void Rational::Set(int numerator, int denominator)

{

numerator_ = numerator;

denominator_ = denominator;

}

std::istream& operator>>(std::istream& in, Rational& r)

{

int numerator {}, denominator {};

in >> numerator;

in >> denominator;

if (!in)

{

// If istream is bad; do not modify 'r'

return in;

}

r.Set(numerator, denominator); // ok due to friendship!

return in;

}

int main()

{

Rational r1(22, 7);

Rational r2(77, 17);

std::cout << "Rational = " << r1 << std::endl;

std::cout << "Call may also be chained due to the signature of the function: " << r1 << " and " << r2 << std::endl;

std::cout << "Enter a rational by separating calls by a space" << std::endl;

std::cin >> r1;

if (std::cin)

std::cout << "Value read is " << r1 << std::endl;

else

std::cout << "Invalid input!" << std::endl;

return EXIT_SUCCESS;

}

```

%% Cell type:markdown id: tags:

This code doesn't run neither in Xeus-cling (due to the operator bug) nor in [Coliru](https://coliru.stacked-crooked.com/) or [Wandbox](https://wandbox.org/)(due to limited `std::cin` support) but you may check it on a local installation.

Even then, it is not perfect: it handles correctly the case gibberish is given through `std::cin`, but if you put more than two blocks separated by spaces the first two ones are used and the others aren't dealt with... As I said, proper and complete handling of input stream is though!

_This notebook is an adaptation of a lecture prepared by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_

_The present version has been written by Sébastien Gilles and Vincent Rouvreau (Inria)_