Commit 07e57f91 authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

Another typo in recommended...

parent f0f79d3d
%% Cell type:markdown id: tags:
# [Getting started in C++](./) - [Operators](./0-main.ipynb) - [Stream operators](./3-Stream.ipynb)
%% Cell type:markdown id: tags:
<h1>Table of contents<span class="tocSkip"></span></h1>
<div class="toc"><ul class="toc-item"><li><span><a href="#Operator-<<" data-toc-modified-id="Operator-<<-1">Operator &lt;&lt;</a></span></li><li><span><a href="#Operator->>" data-toc-modified-id="Operator->>-2">Operator &gt;&gt;</a></span></li></ul></div>
%% Cell type:markdown id: tags:
## Operator <<
So far, we have very often defined methods and/or functions named `Print()` to provide a visual printing of the content of a class.
However, it's even better if we could use the `<<` syntax directly, and the way to do so is to provide an overload of `operator<<`.
The recommanded way to implement it is to use under the hood a `Print(std::ostream&)` (or whatever you want to call it):
The recommended way to implement it is to use under the hood a `Print(std::ostream&)` (or whatever you want to call it):
**Xeus-cling** issue: cling doesn't accept operator definition outside of class; please use [@Coliru](https://coliru.stacked-crooked.com/a/04f59249cce6c131)
%% 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);
// Might even be private; in which case friendship needs to be declared
void Print(std::ostream& out) const;
private :
int numerator_ = 0;
int denominator_ = 0;
};
Rational::Rational(int numerator, int denominator)
: numerator_(numerator),
denominator_(denominator)
{ }
void Rational::Print(std::ostream& out) const
{
out << numerator_ << " / " << denominator_;
}
std::ostream& operator<<(std::ostream& out, const Rational& r)
{
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:
%% Cell type:code id: tags:
``` C++17
// Doesn't run on Xeus-cling!
int main()
{
Rational r1(22, 7);
Rational r2(84, 9);
std::cout << "Rationals = " << r1 << " and " << r2 << std::endl;
return EXIT_SUCCESS;
}
```
%% Cell type:markdown id: tags:
## Operator >>
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)
: numerator_(numerator),
denominator_(denominator)
{ }
void Rational::Print(std::ostream& out) const
{
out << numerator_ << " / " << denominator_;
}
std::ostream& operator<<(std::ostream& out, const Rational& r)
{
r.Print(out);
return out;
}
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!
%% Cell type:markdown id: tags:
© _CNRS 2016_ - _Inria 2018-2021_
_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)_
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment