From 3d2bb200b4913ec676d2d94a02ef701a29076de7 Mon Sep 17 00:00:00 2001
From: Sebastien Gilles <sebastien.gilles@inria.fr>
Date: Tue, 5 Feb 2019 17:18:45 +0100
Subject: [PATCH] TP for operators done. override keyword forgotten in object
 programming solution has been added back.

---
 1-ProceduralProgramming/TP/CMakeLists.txt     |   9 +-
 2-ObjectProgramming/TP/CMakeLists.txt         |   9 +-
 .../TP/Solution/exercice24.cpp                |   2 +-
 .../TP/Solution/exercice25.cpp                |   2 +-
 .../TP/Solution/exercice26.cpp                |   2 +-
 .../TP/Solution/exercice27.cpp                |   2 +-
 .../TP/Solution/exercice28.cpp                |   2 +-
 .../TP/Solution/exercice29.cpp                |   2 +-
 .../TP/Solution/exercice30.cpp                |   2 +-
 3-Operators/0-main.ipynb                      |   5 +-
 3-Operators/1-Intro.ipynb                     | 255 ++++++++-
 3-Operators/1b-TP.ipynb                       | 142 +++++
 3-Operators/1c-SolutionExercice33.ipynb       |  97 ++++
 3-Operators/3b-TP.ipynb                       |  88 +++
 3-Operators/5b-TP.ipynb                       |  86 +++
 3-Operators/TP/CMakeLists.txt                 |  40 ++
 3-Operators/TP/Solution/exercice31.cpp        | 500 +++++++++++++++++
 3-Operators/TP/Solution/exercice32.cpp        | 500 +++++++++++++++++
 3-Operators/TP/Solution/exercice33.cpp        | 508 +++++++++++++++++
 3-Operators/TP/Solution/exercice34.cpp        | 508 +++++++++++++++++
 3-Operators/TP/Solution/exercice35.cpp        | 529 ++++++++++++++++++
 3-Operators/TP/Solution/exercice36.cpp        | 529 ++++++++++++++++++
 3-Operators/TP/initial_file.cpp               | 500 +++++++++++++++++
 5-UsefulConceptsAndSTL/6-SmartPointers.ipynb  |   2 +-
 .../1-ProblematicCase/CMakeLists.txt          |   7 +
 .../2-FixByBuildSystem/CMakeLists.txt         |   8 +
 .../3-FixByPragmas-clang/CMakeLists.txt       |   7 +
 .../4-FixByPragmas-clang-gcc/CMakeLists.txt   |   7 +
 .../5-FixByPragmas-common/CMakeLists.txt      |   7 +
 TP/HowTo.ipynb                                |   2 +-
 30 files changed, 4338 insertions(+), 21 deletions(-)
 create mode 100644 3-Operators/1b-TP.ipynb
 create mode 100644 3-Operators/1c-SolutionExercice33.ipynb
 create mode 100644 3-Operators/3b-TP.ipynb
 create mode 100644 3-Operators/5b-TP.ipynb
 create mode 100644 3-Operators/TP/CMakeLists.txt
 create mode 100644 3-Operators/TP/Solution/exercice31.cpp
 create mode 100644 3-Operators/TP/Solution/exercice32.cpp
 create mode 100644 3-Operators/TP/Solution/exercice33.cpp
 create mode 100644 3-Operators/TP/Solution/exercice34.cpp
 create mode 100644 3-Operators/TP/Solution/exercice35.cpp
 create mode 100644 3-Operators/TP/Solution/exercice36.cpp
 create mode 100644 3-Operators/TP/initial_file.cpp

diff --git a/1-ProceduralProgramming/TP/CMakeLists.txt b/1-ProceduralProgramming/TP/CMakeLists.txt
index 29de5a5..6103282 100644
--- a/1-ProceduralProgramming/TP/CMakeLists.txt
+++ b/1-ProceduralProgramming/TP/CMakeLists.txt
@@ -14,11 +14,10 @@ macro(add_cxx_compiler_flag _flag)
 endmacro()
 
 
-# Don't do such hardcoding in a real project: you want to be able to supersede these settings on command line.
-set(CMAKE_CXX_COMPILER clang++ )
-set(CMAKE_C_COMPILER clang)
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ compiler")
+set(CMAKE_C_COMPILER clang CACHE STRING "C compiler")
+set(CMAKE_CXX_STANDARD 17 CACHE INTEGER "Version of the C++ standard to use")
+set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "If ON the GNU version of the standard is used.")
 
 project(GettingStartedWithModernCpp_TP_Procedural)
 
diff --git a/2-ObjectProgramming/TP/CMakeLists.txt b/2-ObjectProgramming/TP/CMakeLists.txt
index 3962844..6c13425 100644
--- a/2-ObjectProgramming/TP/CMakeLists.txt
+++ b/2-ObjectProgramming/TP/CMakeLists.txt
@@ -14,11 +14,10 @@ macro(add_cxx_compiler_flag _flag)
 endmacro()
 
 
-# Don't do such hardcoding in a real project: you want to be able to supersede these settings on command line.
-set(CMAKE_CXX_COMPILER clang++ )
-set(CMAKE_C_COMPILER clang)
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ compiler")
+set(CMAKE_C_COMPILER clang CACHE STRING "C compiler")
+set(CMAKE_CXX_STANDARD 17 CACHE INTEGER "Version of the C++ standard to use")
+set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "If ON the GNU version of the standard is used.")
 
 project(GettingStartedWithModernCpp_TP_Object)
 
diff --git a/2-ObjectProgramming/TP/Solution/exercice24.cpp b/2-ObjectProgramming/TP/Solution/exercice24.cpp
index fab403e..9e33ffd 100644
--- a/2-ObjectProgramming/TP/Solution/exercice24.cpp
+++ b/2-ObjectProgramming/TP/Solution/exercice24.cpp
@@ -148,7 +148,7 @@ public:
     
     
     //! Print the output for the values 0.65 and 0.35.
-    void Do(int Nbits) const;
+    void Do(int Nbits) const override;
     
 private:
     
diff --git a/2-ObjectProgramming/TP/Solution/exercice25.cpp b/2-ObjectProgramming/TP/Solution/exercice25.cpp
index e04b269..78308d7 100644
--- a/2-ObjectProgramming/TP/Solution/exercice25.cpp
+++ b/2-ObjectProgramming/TP/Solution/exercice25.cpp
@@ -148,7 +148,7 @@ public:
     
     
     //! Print the output for the values 0.65 and 0.35.
-    void Do(int Nbits) const;
+    void Do(int Nbits) const override;
     
 private:
     
diff --git a/2-ObjectProgramming/TP/Solution/exercice26.cpp b/2-ObjectProgramming/TP/Solution/exercice26.cpp
index ea7858d..d58bdeb 100644
--- a/2-ObjectProgramming/TP/Solution/exercice26.cpp
+++ b/2-ObjectProgramming/TP/Solution/exercice26.cpp
@@ -148,7 +148,7 @@ public:
     
     
     //! Print the output for the values 0.65 and 0.35.
-    void Do(int Nbits) const;
+    void Do(int Nbits) const override;
     
 private:
     
diff --git a/2-ObjectProgramming/TP/Solution/exercice27.cpp b/2-ObjectProgramming/TP/Solution/exercice27.cpp
index e14f649..2e89cd2 100644
--- a/2-ObjectProgramming/TP/Solution/exercice27.cpp
+++ b/2-ObjectProgramming/TP/Solution/exercice27.cpp
@@ -148,7 +148,7 @@ public:
     
     
     //! Print the output for the values 0.65 and 0.35.
-    void Do(int Nbits) const;
+    void Do(int Nbits) const override;
     
 private:
     
diff --git a/2-ObjectProgramming/TP/Solution/exercice28.cpp b/2-ObjectProgramming/TP/Solution/exercice28.cpp
index a2fa985..c0dcd44 100644
--- a/2-ObjectProgramming/TP/Solution/exercice28.cpp
+++ b/2-ObjectProgramming/TP/Solution/exercice28.cpp
@@ -148,7 +148,7 @@ public:
     
     
     //! Print the output for the values 0.65 and 0.35.
-    void Do(int Nbits) const;
+    void Do(int Nbits) const override;
     
 private:
     
diff --git a/2-ObjectProgramming/TP/Solution/exercice29.cpp b/2-ObjectProgramming/TP/Solution/exercice29.cpp
index d3054e4..b52412b 100644
--- a/2-ObjectProgramming/TP/Solution/exercice29.cpp
+++ b/2-ObjectProgramming/TP/Solution/exercice29.cpp
@@ -148,7 +148,7 @@ public:
     
     
     //! Print the output for the values 0.65 and 0.35.
-    void Do(int Nbits) const;
+    void Do(int Nbits) const override;
     
 private:
     
diff --git a/2-ObjectProgramming/TP/Solution/exercice30.cpp b/2-ObjectProgramming/TP/Solution/exercice30.cpp
index c539ed0..3a96d0c 100644
--- a/2-ObjectProgramming/TP/Solution/exercice30.cpp
+++ b/2-ObjectProgramming/TP/Solution/exercice30.cpp
@@ -148,7 +148,7 @@ public:
     
     
     //! Print the output for the values 0.65 and 0.35.
-    void Do(int Nbits) const;
+    void Do(int Nbits) const override;
     
 private:
     
diff --git a/3-Operators/0-main.ipynb b/3-Operators/0-main.ipynb
index bee3a00..7c51344 100644
--- a/3-Operators/0-main.ipynb
+++ b/3-Operators/0-main.ipynb
@@ -12,10 +12,13 @@
    "metadata": {},
    "source": [
     "* [Introduction to the concept of operator overload](/notebooks/3-Operators/1-Intro.ipynb)\n",
+    "    * [TP 8](/notebooks/3-Operators/1b-TP.ipynb)\n",
     "* [Comparison operators](/notebooks/3-Operators/2-Comparison.ipynb)\n",
     "* [Stream operators](/notebooks/3-Operators/3-Stream.ipynb)\n",
+    "    * [TP 9](/notebooks/3-Operators/3b-TP.ipynb)\n",
     "* [Affectation operator and the canonical form of a class](/notebooks/3-Operators/4-CanonicalForm.ipynb)\n",
-    "* [Functors](/notebooks/3-Operators/5-Functors.ipynb)"
+    "* [Functors](/notebooks/3-Operators/5-Functors.ipynb)\n",
+    "    * [TP 10](/notebooks/3-Operators/5b-TP.ipynb)"
    ]
   },
   {
diff --git a/3-Operators/1-Intro.ipynb b/3-Operators/1-Intro.ipynb
index 98dd11a..1fd9290 100644
--- a/3-Operators/1-Intro.ipynb
+++ b/3-Operators/1-Intro.ipynb
@@ -14,7 +14,7 @@
    },
    "source": [
     "<h1>Table of contents<span class=\"tocSkip\"></span></h1>\n",
-    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Motivation\" data-toc-modified-id=\"Motivation-1\">Motivation</a></span></li><li><span><a href=\"#Overloading-an-operator\" data-toc-modified-id=\"Overloading-an-operator-2\">Overloading an operator</a></span></li><li><span><a href=\"#Limitations\" data-toc-modified-id=\"Limitations-3\">Limitations</a></span></li><li><span><a href=\"#Conversion-operators\" data-toc-modified-id=\"Conversion-operators-4\">Conversion operators</a></span></li></ul></div>"
+    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Motivation\" data-toc-modified-id=\"Motivation-1\">Motivation</a></span></li><li><span><a href=\"#Overloading-an-operator\" data-toc-modified-id=\"Overloading-an-operator-2\">Overloading an operator</a></span></li><li><span><a href=\"#Operator-between-different-types\" data-toc-modified-id=\"Operator-between-different-types-3\">Operator between different types</a></span></li><li><span><a href=\"#Limitations\" data-toc-modified-id=\"Limitations-4\">Limitations</a></span></li><li><span><a href=\"#Conversion-operators\" data-toc-modified-id=\"Conversion-operators-5\">Conversion operators</a></span></li></ul></div>"
    ]
   },
   {
@@ -311,6 +311,259 @@
     "}"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Operator between different types\n",
+    "\n",
+    "It is also possible to define an operator which acts upon two objects of different nature:\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class Vector4\n",
+    "{\n",
+    "    public :\n",
+    "\n",
+    "        Vector4(double x, double y, double z);\n",
+    "    \n",
+    "        Vector4() = default;\n",
+    "    \n",
+    "        void Print() const;\n",
+    "    \n",
+    "        Vector4 operator+(double value) const\n",
+    "        {\n",
+    "            Vector4 ret;\n",
+    "            ret.x_ = x_ + value;\n",
+    "            ret.y_ = y_ + value;\n",
+    "            ret.z_ = z_ + value;\n",
+    "    \n",
+    "            return ret;\n",
+    "        }\n",
+    "\n",
+    "    private :\n",
+    "    \n",
+    "        double x_ = 0.;\n",
+    "        double y_ = 0.;\n",
+    "        double z_ = 0.;\n",
+    "}; "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#include <iostream>\n",
+    "\n",
+    "void Vector4::Print() const\n",
+    "{\n",
+    "    std::cout << \"(\" << x_ << \", \" << y_ << \", \" << z_ << \")\" << std::endl;\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[1minput_line_12:1:10: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mredefinition of 'Vector4'\u001b[0m\n",
+      "Vector4::Vector4(double x, double y, double z)\n",
+      "\u001b[0;1;32m         ^\n",
+      "\u001b[0m\u001b[1minput_line_9:1:10: \u001b[0m\u001b[0;1;30mnote: \u001b[0mprevious definition is here\u001b[0m\n",
+      "Vector4::Vector4(double x, double y, double z)\n",
+      "\u001b[0;1;32m         ^\n",
+      "\u001b[0m"
+     ]
+    },
+    {
+     "ename": "Interpreter Error",
+     "evalue": "",
+     "output_type": "error",
+     "traceback": [
+      "Interpreter Error: "
+     ]
+    }
+   ],
+   "source": [
+    "Vector4::Vector4(double x, double y, double z)\n",
+    ": x_(x),\n",
+    "y_(y),\n",
+    "z_(z)\n",
+    "{ }"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(10, 8.2, 4)\n"
+     ]
+    }
+   ],
+   "source": [
+    "{\n",
+    "    Vector4 vector(5., 3.2, -1.);\n",
+    "    Vector4 vector_plus_5 = vector + 5.;\n",
+    "    vector_plus_5.Print();\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "However, pay attention to the fact this operator is not commutative: when you call \n",
+    "\n",
+    "````\n",
+    "Vector4 vector_plus_5 = vector + 5.;\n",
+    "````\n",
+    "\n",
+    "it is indeed a shortcut to\n",
+    "\n",
+    "````\n",
+    "Vector4 vector_plus_5 = vector.operator*(5.);\n",
+    "````\n",
+    "\n",
+    "and the following won't compile:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[1minput_line_14:4:32: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1minvalid operands to binary expression ('double' and 'Vector4')\u001b[0m\n",
+      "    Vector4 vector_plus_5 = 5. + vector; // COMPILATION ERROR!\n",
+      "\u001b[0;1;32m                            ~~ ^ ~~~~~~\n",
+      "\u001b[0m"
+     ]
+    },
+    {
+     "ename": "Interpreter Error",
+     "evalue": "",
+     "output_type": "error",
+     "traceback": [
+      "Interpreter Error: "
+     ]
+    }
+   ],
+   "source": [
+    "{\n",
+    "    Vector4 vector(5., 3.2, -1.);\n",
+    "    Vector4 vector_plus_5 = 5. + vector; // COMPILATION ERROR!\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "If you want it to be possible, you have to define the operator with arguments in both orders; you therefore need to use out-of-class prototype of the function (can't show it currently due to Xeus-cling limitation).\n",
+    "\n",
+    "Of course, if you do so you should define one in way of the other:\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "// Won't compile in Xeus-cling\n",
+    "\n",
+    "#include <cstdlib>\n",
+    "#include <iostream>\n",
+    "\n",
+    "class Vector5\n",
+    "{\n",
+    "    public :\n",
+    "\n",
+    "        Vector5(double x, double y, double z);\n",
+    "    \n",
+    "        Vector5() = default;\n",
+    "    \n",
+    "        void Print() const;\n",
+    "    \n",
+    "        friend Vector5 operator+(const Vector5& v, double value);\n",
+    "    \n",
+    "        friend Vector5 operator+(double value, const Vector5& v);\n",
+    "\n",
+    "    private :\n",
+    "    \n",
+    "        double x_ = 0.;\n",
+    "        double y_ = 0.;\n",
+    "        double z_ = 0.;\n",
+    "}; \n",
+    "\n",
+    "\n",
+    "\n",
+    "void Vector5::Print() const\n",
+    "{\n",
+    "    std::cout << \"(\" << x_ << \", \" << y_ << \", \" << z_ << \")\" << std::endl;\n",
+    "}\n",
+    "\n",
+    "\n",
+    "Vector5::Vector5(double x, double y, double z)\n",
+    ": x_(x),\n",
+    "y_(y),\n",
+    "z_(z)\n",
+    "{ }\n",
+    "\n",
+    "\n",
+    "\n",
+    "Vector5 operator+(const Vector5& v, double value)\n",
+    "{\n",
+    "    Vector5 ret;\n",
+    "    \n",
+    "    ret.x_ = v.x_ + value;\n",
+    "    ret.y_ = v.y_ + value;\n",
+    "    ret.z_ = v.z_ + value;\n",
+    "    \n",
+    "    return ret;\n",
+    "}\n",
+    "\n",
+    "\n",
+    "Vector5 operator+(double value, const Vector5& v)\n",
+    "{\n",
+    "    return v + value;\n",
+    "}\n",
+    "\n",
+    "\n",
+    "int main(int argc, char** argv)\n",
+    "{\n",
+    "    Vector5 vector(5., 3.2, -1.);\n",
+    "    Vector5 vector_plus_5 = vector + 5.;\n",
+    "    Vector5 vector_plus_5_commutated = 5. + vector;\n",
+    "    \n",
+    "    vector_plus_5.Print();\n",
+    "    vector_plus_5_commutated.Print();\n",
+    "    \n",
+    "    return EXIT_SUCCESS;\n",
+    "}\n"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
diff --git a/3-Operators/1b-TP.ipynb b/3-Operators/1b-TP.ipynb
new file mode 100644
index 0000000..95c598d
--- /dev/null
+++ b/3-Operators/1b-TP.ipynb
@@ -0,0 +1,142 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# [Getting started in C++](/) - [Operators](/notebooks/3-Operators/0-main.ipynb) - [TP 8](/notebooks/3-Operators/1b-TP.ipynb)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "toc": true
+   },
+   "source": [
+    "<h1>Table of contents<span class=\"tocSkip\"></span></h1>\n",
+    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Introduction\" data-toc-modified-id=\"Introduction-1\">Introduction</a></span></li><li><span><a href=\"#EXERCICE-31:-replace-PowerOfTwoApprox::DoubleValue-by-an-operator-double\" data-toc-modified-id=\"EXERCICE-31:-replace-PowerOfTwoApprox::DoubleValue-by-an-operator-double-2\">EXERCICE 31: replace <code>PowerOfTwoApprox::DoubleValue</code> by an <code>operator double</code></a></span></li><li><span><a href=\"#EXERCICE-32:-replace-PowerOfTwoApprox::Multiply-by-operator-*\" data-toc-modified-id=\"EXERCICE-32:-replace-PowerOfTwoApprox::Multiply-by-operator-*-3\">EXERCICE 32: replace <code>PowerOfTwoApprox::Multiply</code> by <code>operator *</code></a></span></li><li><span><a href=\"#EXERCICE-33:-commutativity\" data-toc-modified-id=\"EXERCICE-33:-commutativity-4\">EXERCICE 33: commutativity</a></span></li><li><span><a href=\"#EXERCICE-34:-operator[]\" data-toc-modified-id=\"EXERCICE-34:-operator[]-5\">EXERCICE 34: <code>operator[]</code></a></span></li></ul></div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Introduction\n",
+    "\n",
+    "[This notebook](/notebooks/TP/HowTo.ipynb) explains very briefly your options to run the TP.\n",
+    "\n",
+    "We will start from the solution to exercice 30 of the procedural object TP. `initial_file.cpp` in the TP directory is a copy to the solution of this exercice (symbolic link wouldn't have worked with Docker)."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### EXERCICE 31: replace `PowerOfTwoApprox::DoubleValue` by an `operator double`\n",
+    "\n",
+    "The arguments should remain the same."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### EXERCICE 32: replace `PowerOfTwoApprox::Multiply` by `operator *`\n",
+    "\n",
+    "Arguments remain unchanged."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### EXERCICE 33: commutativity\n",
+    "\n",
+    "In `TestDisplaySum::Display()`, you should have the line\n",
+    "\n",
+    "````\n",
+    "int approx = approx1 * coefficient1 + approx2 * coefficient2;\n",
+    "````\n",
+    "\n",
+    "Try the following one instead:\n",
+    "\n",
+    "````\n",
+    "int approx = coefficient1 * approx1 + coefficient2 * approx2;\n",
+    "````\n",
+    "\n",
+    "You should get at least a warning doing so... (at least with the CMake build I provide that activates `-Wconversion` warning - more on that [later](/notebooks/6-InRealEnvironment/3-Compilers.ipynb)...)\n",
+    "\n",
+    "Add a print line in `operator*`.\n",
+    "\n",
+    "Do you understand what happens? \n",
+    "\n",
+    "[Solution](/notebooks/3-Operators/1c-SolutionExercice33.ipynb)\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### EXERCICE 34: `operator[]`\n",
+    "\n",
+    "In `TestDisplayContainer`, replace `GetElement()` method by `operator[]`."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "© _CNRS 2016_ - _Inria 2018_   \n",
+    "_This notebook is an adaptation of a lecture prepared and redacted 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/)_  \n",
+    "_The present version has been redacted by Sébastien Gilles and Vincent Rouvreau (Inria)_"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++17",
+   "language": "C++17",
+   "name": "xeus-cling-cpp17"
+  },
+  "language_info": {
+   "codemirror_mode": "text/x-c++src",
+   "file_extension": ".cpp",
+   "mimetype": "text/x-c++src",
+   "name": "c++",
+   "version": "-std=c++17"
+  },
+  "latex_envs": {
+   "LaTeX_envs_menu_present": true,
+   "autoclose": false,
+   "autocomplete": true,
+   "bibliofile": "biblio.bib",
+   "cite_by": "apalike",
+   "current_citInitial": 1,
+   "eqLabelWithNumbers": true,
+   "eqNumInitial": 1,
+   "hotkeys": {
+    "equation": "Ctrl-E",
+    "itemize": "Ctrl-I"
+   },
+   "labels_anchors": false,
+   "latex_user_defs": false,
+   "report_style_numbering": false,
+   "user_envs_cfg": false
+  },
+  "toc": {
+   "base_numbering": 1,
+   "nav_menu": {},
+   "number_sections": false,
+   "sideBar": true,
+   "skip_h1_title": true,
+   "title_cell": "Table of contents",
+   "title_sidebar": "Contents",
+   "toc_cell": true,
+   "toc_position": {},
+   "toc_section_display": true,
+   "toc_window_display": true
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/3-Operators/1c-SolutionExercice33.ipynb b/3-Operators/1c-SolutionExercice33.ipynb
new file mode 100644
index 0000000..d1c51a0
--- /dev/null
+++ b/3-Operators/1c-SolutionExercice33.ipynb
@@ -0,0 +1,97 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# [Getting started in C++](/) - [Operators](/notebooks/3-Operators/0-main.ipynb) - [TP 8 - Solution](/notebooks/3-Operators/1b-TP.ipynb)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "toc": true
+   },
+   "source": [
+    "<h1>Table of contents<span class=\"tocSkip\"></span></h1>\n",
+    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#EXERCICE-33:-commutativity\" data-toc-modified-id=\"EXERCICE-33:-commutativity-1\">EXERCICE 33: commutativity</a></span></li></ul></div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### EXERCICE 33: commutativity\n",
+    "\n",
+    "What happens in fact is that `operator*` is not commutative: it expects as first argument an object and as second argument an integer.\n",
+    "\n",
+    "So why does it work nonetheless?\n",
+    "\n",
+    "`operator*(int, PowerOfTwoApprox)` is not defined... but addition between an integer and a double is obviously possible, AND you've just defined before an implicit conversion to `double`.\n",
+    "\n",
+    "You should of course heed the warning and fix your code:\n",
+    "\n",
+    "* Make `operator double` explicit. Except in very specific cases, I advise you to always make such conversion operators explicit to avoid unintended side effects as the one we've just got.\n",
+    "* If commutativity is important for you, make `operator*` a friend function instead of a method and provide both ordering of arguments. \n",
+    "\n",
+    "The solution file implements both these modifications."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "© _CNRS 2016_ - _Inria 2018_   \n",
+    "_This notebook is an adaptation of a lecture prepared and redacted 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/)_  \n",
+    "_The present version has been redacted by Sébastien Gilles and Vincent Rouvreau (Inria)_"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++17",
+   "language": "C++17",
+   "name": "xeus-cling-cpp17"
+  },
+  "language_info": {
+   "codemirror_mode": "text/x-c++src",
+   "file_extension": ".cpp",
+   "mimetype": "text/x-c++src",
+   "name": "c++",
+   "version": "-std=c++17"
+  },
+  "latex_envs": {
+   "LaTeX_envs_menu_present": true,
+   "autoclose": false,
+   "autocomplete": true,
+   "bibliofile": "biblio.bib",
+   "cite_by": "apalike",
+   "current_citInitial": 1,
+   "eqLabelWithNumbers": true,
+   "eqNumInitial": 1,
+   "hotkeys": {
+    "equation": "Ctrl-E",
+    "itemize": "Ctrl-I"
+   },
+   "labels_anchors": false,
+   "latex_user_defs": false,
+   "report_style_numbering": false,
+   "user_envs_cfg": false
+  },
+  "toc": {
+   "base_numbering": 1,
+   "nav_menu": {},
+   "number_sections": false,
+   "sideBar": true,
+   "skip_h1_title": true,
+   "title_cell": "Table of contents",
+   "title_sidebar": "Contents",
+   "toc_cell": true,
+   "toc_position": {},
+   "toc_section_display": true,
+   "toc_window_display": true
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/3-Operators/3b-TP.ipynb b/3-Operators/3b-TP.ipynb
new file mode 100644
index 0000000..31ad741
--- /dev/null
+++ b/3-Operators/3b-TP.ipynb
@@ -0,0 +1,88 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# [Getting started in C++](/) - [Operators](/notebooks/3-Operators/0-main.ipynb) - [TP 9](/notebooks/3-Operators/3b-TP.ipynb)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "toc": true
+   },
+   "source": [
+    "<h1>Table of contents<span class=\"tocSkip\"></span></h1>\n",
+    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#EXERCICE-35:-operator<<\" data-toc-modified-id=\"EXERCICE-35:-operator<<-1\">EXERCICE 35: <code>operator&lt;&lt;</code></a></span></li></ul></div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### EXERCICE 35: `operator<<`\n",
+    "\n",
+    "Introduce an `operator<<` for class `PowerOfTwoApprox` which provides the numerator and exponent used, e.g. `10/2^4`.\n",
+    "\n",
+    "Use it in `TestDisplayPowerOfTwoApprox::Display()`."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "© _CNRS 2016_ - _Inria 2018_   \n",
+    "_This notebook is an adaptation of a lecture prepared and redacted 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/)_  \n",
+    "_The present version has been redacted by Sébastien Gilles and Vincent Rouvreau (Inria)_"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++17",
+   "language": "C++17",
+   "name": "xeus-cling-cpp17"
+  },
+  "language_info": {
+   "codemirror_mode": "text/x-c++src",
+   "file_extension": ".cpp",
+   "mimetype": "text/x-c++src",
+   "name": "c++",
+   "version": "-std=c++17"
+  },
+  "latex_envs": {
+   "LaTeX_envs_menu_present": true,
+   "autoclose": false,
+   "autocomplete": true,
+   "bibliofile": "biblio.bib",
+   "cite_by": "apalike",
+   "current_citInitial": 1,
+   "eqLabelWithNumbers": true,
+   "eqNumInitial": 1,
+   "hotkeys": {
+    "equation": "Ctrl-E",
+    "itemize": "Ctrl-I"
+   },
+   "labels_anchors": false,
+   "latex_user_defs": false,
+   "report_style_numbering": false,
+   "user_envs_cfg": false
+  },
+  "toc": {
+   "base_numbering": 1,
+   "nav_menu": {},
+   "number_sections": false,
+   "sideBar": true,
+   "skip_h1_title": true,
+   "title_cell": "Table of contents",
+   "title_sidebar": "Contents",
+   "toc_cell": true,
+   "toc_position": {},
+   "toc_section_display": true,
+   "toc_window_display": true
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/3-Operators/5b-TP.ipynb b/3-Operators/5b-TP.ipynb
new file mode 100644
index 0000000..56bc68b
--- /dev/null
+++ b/3-Operators/5b-TP.ipynb
@@ -0,0 +1,86 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# [Getting started in C++](/) - [Operators](/notebooks/3-Operators/0-main.ipynb) - [TP 10](/notebooks/3-Operators/5b-TP.ipynb)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "toc": true
+   },
+   "source": [
+    "<h1>Table of contents<span class=\"tocSkip\"></span></h1>\n",
+    "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#EXERCICE-36:-functor\" data-toc-modified-id=\"EXERCICE-36:-functor-1\">EXERCICE 36: functor</a></span></li></ul></div>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### EXERCICE 36: functor\n",
+    "\n",
+    "Replace method `Do()` in `TestDisplay` and its derived classes by a functor."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "© _CNRS 2016_ - _Inria 2018_   \n",
+    "_This notebook is an adaptation of a lecture prepared and redacted 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/)_  \n",
+    "_The present version has been redacted by Sébastien Gilles and Vincent Rouvreau (Inria)_"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++17",
+   "language": "C++17",
+   "name": "xeus-cling-cpp17"
+  },
+  "language_info": {
+   "codemirror_mode": "text/x-c++src",
+   "file_extension": ".cpp",
+   "mimetype": "text/x-c++src",
+   "name": "c++",
+   "version": "-std=c++17"
+  },
+  "latex_envs": {
+   "LaTeX_envs_menu_present": true,
+   "autoclose": false,
+   "autocomplete": true,
+   "bibliofile": "biblio.bib",
+   "cite_by": "apalike",
+   "current_citInitial": 1,
+   "eqLabelWithNumbers": true,
+   "eqNumInitial": 1,
+   "hotkeys": {
+    "equation": "Ctrl-E",
+    "itemize": "Ctrl-I"
+   },
+   "labels_anchors": false,
+   "latex_user_defs": false,
+   "report_style_numbering": false,
+   "user_envs_cfg": false
+  },
+  "toc": {
+   "base_numbering": 1,
+   "nav_menu": {},
+   "number_sections": false,
+   "sideBar": true,
+   "skip_h1_title": true,
+   "title_cell": "Table of contents",
+   "title_sidebar": "Contents",
+   "toc_cell": true,
+   "toc_position": {},
+   "toc_section_display": true,
+   "toc_window_display": true
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/3-Operators/TP/CMakeLists.txt b/3-Operators/TP/CMakeLists.txt
new file mode 100644
index 0000000..4112ab8
--- /dev/null
+++ b/3-Operators/TP/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required(VERSION 3.9)
+
+# Add a compiler flag only if it is accepted.
+# This macro is usually defined once and for all in a specific file which is included in the CMakeLists.txt in which
+# you need it. 
+include(CheckCXXCompilerFlag)
+macro(add_cxx_compiler_flag _flag)
+  string(REPLACE "-" "_" _flag_var ${_flag})
+  check_cxx_compiler_flag("${_flag}" CXX_COMPILER_${_flag_var}_OK)
+
+  if(CXX_COMPILER_${_flag_var}_OK)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_flag}")
+  endif()
+endmacro()
+
+
+set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ compiler")
+set(CMAKE_C_COMPILER clang CACHE STRING "C compiler")
+set(CMAKE_CXX_STANDARD 17 CACHE INTEGER "Version of the C++ standard to use")
+set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "If ON the GNU version of the standard is used.")
+
+project(GettingStartedWithModernCpp_TP_Operators)
+
+
+add_cxx_compiler_flag("-Weverything") # all warnings for clang
+add_cxx_compiler_flag("-Wall") # for gcc (and recognized by clang)
+add_cxx_compiler_flag("-Wextra") # for gcc  (and recognized by clang)
+add_cxx_compiler_flag("-Wconversion")# for gcc
+add_cxx_compiler_flag("-Wno-c++98-compat") # We assume we are using modern C++
+add_cxx_compiler_flag("-Wno-c++98-compat-pedantic") # We assume we are using modern C++
+add_cxx_compiler_flag("-Wno-padded")
+
+
+add_executable(initial initial_file.cpp)
+add_executable(exercice31 exercice31.cpp)
+add_executable(exercice32 exercice32.cpp)
+add_executable(exercice33 exercice33.cpp)
+add_executable(exercice34 exercice34.cpp)
+add_executable(exercice35 exercice35.cpp)
+add_executable(exercice36 exercice36.cpp)
\ No newline at end of file
diff --git a/3-Operators/TP/Solution/exercice31.cpp b/3-Operators/TP/Solution/exercice31.cpp
new file mode 100644
index 0000000..085f506
--- /dev/null
+++ b/3-Operators/TP/Solution/exercice31.cpp
@@ -0,0 +1,500 @@
+#include <iostream>
+#include <cmath> // for std::round
+#include <string>
+#include <sstream> // for std::ostringstream
+
+
+/************************************/
+// Declarations 
+/************************************/
+
+/*!
+ * \brief  Structure to group together numerator and exponent used to represent a floating-point.
+ * 
+ * Representation is numerator / 2^exponent, where numerator is as large as a selected number of bits make possible.
+ */
+class PowerOfTwoApprox
+{
+public:
+    //! Constructor that compute the best possible approximation of `value` with `Nbits`
+    PowerOfTwoApprox(int Nbits, double value);
+    
+    //! Returns the double value computed from `numerator_` and `exponent_`.
+    operator double() const;
+    
+   /*! 
+    * \brief Multiply the approximate representation by an integer. 
+    * 
+    * \param[in] coefficient Integer coefficient by which the object is multiplied.
+    * 
+    * \return An approximate integer result of the multiplication.
+    */
+    int Multiply(int coefficient);
+    
+    //! Get the value of the numerator.
+    int Numerator() const;
+    
+    //! Get the value of the exponent.
+    int Exponent() const;
+        
+private:
+    
+    //! Numerator.
+    int numerator_ = 0;
+    
+    //! Exponent applied to the 2 at the denominator.
+    int exponent_ = 0;    
+};
+
+
+
+/*!
+ * \brief Base class for TestDisplayPowerOfTwoApprox and TestDisplaySum.
+ */
+class TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplay(int resolution);
+    
+    //! Virtual method.
+    virtual void Do(int Nbits) const = 0;
+    
+    //! Virtual destructor.
+    virtual ~TestDisplay();
+    
+protected:
+    
+   /*!
+    * \brief  Print a line with information about error.
+    *
+    * \param[in] after_bit_string String that might appear
+    */
+   void PrintNumericalError(int Nbits, double exact, double approx,
+                            std::string after_bit_string, std::string before_error) const;
+                              
+    
+private:
+    
+    //! Maximum error index.
+    const int resolution_;
+
+};
+
+
+
+/*!
+ * \brief Class in charge of displaying the approximation for PowerOfTwoApprox for a value which is expected
+ * to be provided in a derived class.
+ */
+class TestDisplayPowerOfTwoApprox : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox(int resolution);
+    
+    //! Virtual destructor.
+    virtual ~TestDisplayPowerOfTwoApprox();
+    
+protected:
+    
+    //! Print the output for `value` when `Nbits` are available.
+    void Display(int Nbits, double value) const;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.65
+class TestDisplayPowerOfTwoApprox065 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox065(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.35
+class TestDisplayPowerOfTwoApprox035 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox035(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+    
+    
+
+/*!
+ * \brief Class in charge of displaying the approximation for 0.65 * 3515 + 0.35 * 4832.
+
+ */
+class TestDisplaySum : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplaySum(int resolution);
+    
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+    
+private:
+    
+    //! Print the output for the approximation of the sum value1 * coefficient1 + value2 * coefficient2.
+    void Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const;
+
+};
+
+
+//! Returns `number` * (2 ^ `exponent`) 
+int times_power_of_2(int number, int exponent);
+
+
+//! Round to `x` the nearest integer.
+int round_as_int(double x);
+
+
+//! Maximum integer that might be represented with `Nbits` bits.
+int max_int(int Nbits);
+
+
+//! Function to call when an error occurred; its aborts the program.
+[[noreturn]] void error(std::string explanation);
+
+
+//! Class which stores several `TestDisplay` as pointers.
+class TestDisplayContainer
+{
+public:
+    
+    //! Constructor.
+    TestDisplayContainer(std::size_t size);
+    
+    //! Destructor.
+    ~TestDisplayContainer();
+        
+    //! Insert a new `TestDisplay` object at the `next_position_available_`.
+    void Register(TestDisplay* test_display);
+    
+    //! Returns the number of registered elements.
+    int Nelement() const;
+    
+    //! Provide access to the `i`-th element.
+    TestDisplay& GetElement(int i) const;
+
+private:
+    
+    //! Store `TestDisplay` objects upon which the display will be called.
+    TestDisplay** test_display_list_;
+    
+    //! Size of the array.
+    const std::size_t size_ = 0;
+
+    //! Position in which the next `TestDisplay` will be put.
+    int next_position_available_ = 0;
+};
+
+
+//! Loop over the content of `TestDisplayContainer`.
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container);
+
+
+/************************************/
+// Main function
+/************************************/
+
+int main(int argc, char** argv)
+{
+    static_cast<void>(argc); // to silence warning about unused argc - don't bother 
+    static_cast<void>(argv); // to silence warning about unused argv - don't bother 
+        
+    TestDisplayContainer container(3);
+    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
+    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
+    container.Register(new TestDisplaySum(1000000));
+    
+    loop(4, 16, 4, container);
+
+    return EXIT_SUCCESS;
+}
+
+
+/************************************/
+// Definitions
+/************************************/
+
+
+int times_power_of_2(int number, int exponent)
+{
+    while (exponent > 0)
+    { 
+        number *= 2; 
+        exponent -= 1; 
+    }
+    while (exponent < 0)
+    { 
+        number /= 2;
+        exponent += 1 ; 
+    }
+    
+    return number;
+}
+
+
+int round_as_int(double x)
+{
+    return static_cast<int>(std::round(x));
+}
+
+
+int max_int(int Nbits)
+{ 
+    return (times_power_of_2(1, Nbits) - 1);
+}
+
+
+[[noreturn]] void error(std::string explanation)
+{
+    std::cout << "ERROR: " << explanation << std::endl;
+    exit(EXIT_FAILURE);
+}
+
+
+/*==================================*/
+// PowerOfTwoApprox
+/*==================================*/
+
+PowerOfTwoApprox::PowerOfTwoApprox(int Nbits, double value)
+{
+    auto& numerator = numerator_;
+    auto& exponent = exponent_;
+    
+    numerator = exponent = 0;
+    int denominator {};
+    
+    int max_numerator = max_int(Nbits);
+    
+    do
+    {
+        ++exponent;
+        denominator = times_power_of_2(1, exponent);   
+        numerator = round_as_int(value * denominator);
+    }
+    while (numerator <= max_numerator);
+    
+    --exponent;
+    denominator = times_power_of_2(1, exponent); 
+    numerator = round_as_int(value * denominator);
+}
+
+
+PowerOfTwoApprox::operator double() const
+{
+    int denominator = times_power_of_2(1, exponent_); 
+    return static_cast<double>(numerator_) / denominator;
+}
+
+
+int PowerOfTwoApprox::Numerator() const
+{
+    return numerator_;
+}
+
+
+int PowerOfTwoApprox::Exponent() const
+{
+    return exponent_;
+}
+
+
+int PowerOfTwoApprox::Multiply(int coefficient)
+{
+    return times_power_of_2(Numerator() * coefficient, -Exponent());
+}
+
+
+/*==================================*/
+// TestDisplay
+/*==================================*/
+
+TestDisplay::TestDisplay(int resolution)
+: resolution_(resolution)
+{ }
+
+
+TestDisplay::~TestDisplay() = default;
+
+
+void TestDisplay::PrintNumericalError(int Nbits, double exact, double approx,
+                                      std::string after_bit_string, std::string before_error) const
+{
+    int error = round_as_int(resolution_ * std::fabs(exact - approx) / exact);
+    
+    std::cout << "[With " << Nbits << " bits]: " << after_bit_string
+        << exact << " ~ " << approx
+        << before_error
+        << "  [error = " << error << "/" << resolution_ << "]" 
+        << std::endl;    
+}
+
+
+/*==================================*/
+// TestDisplayPowerOfTwoApprox
+/*==================================*/
+
+TestDisplayPowerOfTwoApprox::TestDisplayPowerOfTwoApprox(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox::~TestDisplayPowerOfTwoApprox() = default;
+
+
+void TestDisplayPowerOfTwoApprox::Display(int Nbits, double value) const
+{
+    PowerOfTwoApprox approx(Nbits, value);
+    
+    auto numerator = approx.Numerator();
+    auto exponent = approx.Exponent();
+
+    double double_approx = static_cast<double>(approx);
+    
+    std::ostringstream oconv;
+    oconv << "  (" << numerator << "/2^" << exponent << ")";
+    
+    PrintNumericalError(Nbits, value, double_approx, "", oconv.str());
+}
+
+
+TestDisplayPowerOfTwoApprox065::TestDisplayPowerOfTwoApprox065(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox035::TestDisplayPowerOfTwoApprox035(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+void TestDisplayPowerOfTwoApprox065::Do(int Nbits) const
+{
+    Display(Nbits, 0.65);
+}
+
+
+void TestDisplayPowerOfTwoApprox035::Do(int Nbits) const
+{
+    Display(Nbits, 0.35);
+}
+
+
+
+/*==================================*/
+// TestDisplaySum
+/*==================================*/
+
+TestDisplaySum::TestDisplaySum(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+void TestDisplaySum::Do(int Nbits) const
+{
+    Display(Nbits, 0.65, 3515, 0.35, 4832);
+}
+
+
+void TestDisplaySum::Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const
+{
+    double exact = std::round(value1 * coefficient1 + value2 * coefficient2);
+
+    PowerOfTwoApprox approx1(Nbits, value1);
+    PowerOfTwoApprox approx2(Nbits, value2);
+
+    int approx = approx1.Multiply(coefficient1) + approx2.Multiply(coefficient2);
+    
+    std::ostringstream oconv;
+    oconv << value1 << " * " << coefficient1  << " + " << value2 << " * " << coefficient2 << " = ";
+    
+    PrintNumericalError(Nbits, exact, static_cast<double>(approx), oconv.str(), "");
+}
+
+
+/*==================================*/
+// TestDisplayContainer
+/*==================================*/
+
+TestDisplayContainer::TestDisplayContainer(std::size_t size)
+: size_(size)
+{
+    test_display_list_ = new TestDisplay*[size];
+
+    for (auto i = 0ul; i < size; ++i)
+        test_display_list_[i] = nullptr;
+}
+
+
+TestDisplayContainer::~TestDisplayContainer()
+{
+    for (int position = 0; position < next_position_available_; ++position)
+        delete test_display_list_[position];
+    
+    delete[] test_display_list_;
+}
+
+
+void TestDisplayContainer::Register(TestDisplay* test_display)
+{
+    if (next_position_available_ >= static_cast<int>(size_))
+        error("Too many `TestDisplay` registered!");
+    
+    test_display_list_[next_position_available_++] = test_display;
+}
+
+
+int TestDisplayContainer::Nelement() const
+{
+    return next_position_available_;
+}
+
+
+TestDisplay& TestDisplayContainer::GetElement(int i) const
+{
+    if (i < 0 || i >= next_position_available_)
+        error("Invalid index in TestDisplayContainer::GetElement() request!");
+    
+    decltype(auto) element_ptr = test_display_list_[i];
+    return *element_ptr;
+}
+    
+
+
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container)
+{
+    int Nelement = container.Nelement();
+    
+    for (int position = 0; position < Nelement; ++position)
+    {
+        decltype(auto) test_display = container.GetElement(position);
+        
+        for (int Nbits = Nbits_min; Nbits <= Nbits_max; Nbits += Nbits_increment)
+             test_display.Do(Nbits); 
+    
+        std::cout << std::endl;
+    }    
+}
+    
+    
+
diff --git a/3-Operators/TP/Solution/exercice32.cpp b/3-Operators/TP/Solution/exercice32.cpp
new file mode 100644
index 0000000..a4d5c59
--- /dev/null
+++ b/3-Operators/TP/Solution/exercice32.cpp
@@ -0,0 +1,500 @@
+#include <iostream>
+#include <cmath> // for std::round
+#include <string>
+#include <sstream> // for std::ostringstream
+
+
+/************************************/
+// Declarations 
+/************************************/
+
+/*!
+ * \brief  Structure to group together numerator and exponent used to represent a floating-point.
+ * 
+ * Representation is numerator / 2^exponent, where numerator is as large as a selected number of bits make possible.
+ */
+class PowerOfTwoApprox
+{
+public:
+    //! Constructor that compute the best possible approximation of `value` with `Nbits`
+    PowerOfTwoApprox(int Nbits, double value);
+    
+    //! Returns the double value computed from `numerator_` and `exponent_`.
+    operator double() const;
+    
+   /*! 
+    * \brief Multiply the approximate representation by an integer. 
+    * 
+    * \param[in] coefficient Integer coefficient by which the object is multiplied.
+    * 
+    * \return An approximate integer result of the multiplication.
+    */
+    int operator*(int coefficient);
+    
+    //! Get the value of the numerator.
+    int Numerator() const;
+    
+    //! Get the value of the exponent.
+    int Exponent() const;
+        
+private:
+    
+    //! Numerator.
+    int numerator_ = 0;
+    
+    //! Exponent applied to the 2 at the denominator.
+    int exponent_ = 0;    
+};
+
+
+
+/*!
+ * \brief Base class for TestDisplayPowerOfTwoApprox and TestDisplaySum.
+ */
+class TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplay(int resolution);
+    
+    //! Virtual method.
+    virtual void Do(int Nbits) const = 0;
+    
+    //! Virtual destructor.
+    virtual ~TestDisplay();
+    
+protected:
+    
+   /*!
+    * \brief  Print a line with information about error.
+    *
+    * \param[in] after_bit_string String that might appear
+    */
+   void PrintNumericalError(int Nbits, double exact, double approx,
+                            std::string after_bit_string, std::string before_error) const;
+                              
+    
+private:
+    
+    //! Maximum error index.
+    const int resolution_;
+
+};
+
+
+
+/*!
+ * \brief Class in charge of displaying the approximation for PowerOfTwoApprox for a value which is expected
+ * to be provided in a derived class.
+ */
+class TestDisplayPowerOfTwoApprox : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox(int resolution);
+    
+    //! Virtual destructor.
+    virtual ~TestDisplayPowerOfTwoApprox();
+    
+protected:
+    
+    //! Print the output for `value` when `Nbits` are available.
+    void Display(int Nbits, double value) const;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.65
+class TestDisplayPowerOfTwoApprox065 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox065(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.35
+class TestDisplayPowerOfTwoApprox035 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox035(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+    
+    
+
+/*!
+ * \brief Class in charge of displaying the approximation for 0.65 * 3515 + 0.35 * 4832.
+
+ */
+class TestDisplaySum : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplaySum(int resolution);
+    
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+    
+private:
+    
+    //! Print the output for the approximation of the sum value1 * coefficient1 + value2 * coefficient2.
+    void Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const;
+
+};
+
+
+//! Returns `number` * (2 ^ `exponent`) 
+int times_power_of_2(int number, int exponent);
+
+
+//! Round to `x` the nearest integer.
+int round_as_int(double x);
+
+
+//! Maximum integer that might be represented with `Nbits` bits.
+int max_int(int Nbits);
+
+
+//! Function to call when an error occurred; its aborts the program.
+[[noreturn]] void error(std::string explanation);
+
+
+//! Class which stores several `TestDisplay` as pointers.
+class TestDisplayContainer
+{
+public:
+    
+    //! Constructor.
+    TestDisplayContainer(std::size_t size);
+    
+    //! Destructor.
+    ~TestDisplayContainer();
+        
+    //! Insert a new `TestDisplay` object at the `next_position_available_`.
+    void Register(TestDisplay* test_display);
+    
+    //! Returns the number of registered elements.
+    int Nelement() const;
+    
+    //! Provide access to the `i`-th element.
+    TestDisplay& GetElement(int i) const;
+
+private:
+    
+    //! Store `TestDisplay` objects upon which the display will be called.
+    TestDisplay** test_display_list_;
+    
+    //! Size of the array.
+    const std::size_t size_ = 0;
+
+    //! Position in which the next `TestDisplay` will be put.
+    int next_position_available_ = 0;
+};
+
+
+//! Loop over the content of `TestDisplayContainer`.
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container);
+
+
+/************************************/
+// Main function
+/************************************/
+
+int main(int argc, char** argv)
+{
+    static_cast<void>(argc); // to silence warning about unused argc - don't bother 
+    static_cast<void>(argv); // to silence warning about unused argv - don't bother 
+        
+    TestDisplayContainer container(3);
+    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
+    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
+    container.Register(new TestDisplaySum(1000000));
+    
+    loop(4, 16, 4, container);
+
+    return EXIT_SUCCESS;
+}
+
+
+/************************************/
+// Definitions
+/************************************/
+
+
+int times_power_of_2(int number, int exponent)
+{
+    while (exponent > 0)
+    { 
+        number *= 2; 
+        exponent -= 1; 
+    }
+    while (exponent < 0)
+    { 
+        number /= 2;
+        exponent += 1 ; 
+    }
+    
+    return number;
+}
+
+
+int round_as_int(double x)
+{
+    return static_cast<int>(std::round(x));
+}
+
+
+int max_int(int Nbits)
+{ 
+    return (times_power_of_2(1, Nbits) - 1);
+}
+
+
+[[noreturn]] void error(std::string explanation)
+{
+    std::cout << "ERROR: " << explanation << std::endl;
+    exit(EXIT_FAILURE);
+}
+
+
+/*==================================*/
+// PowerOfTwoApprox
+/*==================================*/
+
+PowerOfTwoApprox::PowerOfTwoApprox(int Nbits, double value)
+{
+    auto& numerator = numerator_;
+    auto& exponent = exponent_;
+    
+    numerator = exponent = 0;
+    int denominator {};
+    
+    int max_numerator = max_int(Nbits);
+    
+    do
+    {
+        ++exponent;
+        denominator = times_power_of_2(1, exponent);   
+        numerator = round_as_int(value * denominator);
+    }
+    while (numerator <= max_numerator);
+    
+    --exponent;
+    denominator = times_power_of_2(1, exponent); 
+    numerator = round_as_int(value * denominator);
+}
+
+
+PowerOfTwoApprox::operator double() const
+{
+    int denominator = times_power_of_2(1, exponent_); 
+    return static_cast<double>(numerator_) / denominator;
+}
+
+
+int PowerOfTwoApprox::Numerator() const
+{
+    return numerator_;
+}
+
+
+int PowerOfTwoApprox::Exponent() const
+{
+    return exponent_;
+}
+
+
+int PowerOfTwoApprox::operator*(int coefficient)
+{
+    return times_power_of_2(Numerator() * coefficient, -Exponent());
+}
+
+
+/*==================================*/
+// TestDisplay
+/*==================================*/
+
+TestDisplay::TestDisplay(int resolution)
+: resolution_(resolution)
+{ }
+
+
+TestDisplay::~TestDisplay() = default;
+
+
+void TestDisplay::PrintNumericalError(int Nbits, double exact, double approx,
+                                      std::string after_bit_string, std::string before_error) const
+{
+    int error = round_as_int(resolution_ * std::fabs(exact - approx) / exact);
+    
+    std::cout << "[With " << Nbits << " bits]: " << after_bit_string
+        << exact << " ~ " << approx
+        << before_error
+        << "  [error = " << error << "/" << resolution_ << "]" 
+        << std::endl;    
+}
+
+
+/*==================================*/
+// TestDisplayPowerOfTwoApprox
+/*==================================*/
+
+TestDisplayPowerOfTwoApprox::TestDisplayPowerOfTwoApprox(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox::~TestDisplayPowerOfTwoApprox() = default;
+
+
+void TestDisplayPowerOfTwoApprox::Display(int Nbits, double value) const
+{
+    PowerOfTwoApprox approx(Nbits, value);
+    
+    auto numerator = approx.Numerator();
+    auto exponent = approx.Exponent();
+
+    double double_approx = static_cast<double>(approx);
+    
+    std::ostringstream oconv;
+    oconv << "  (" << numerator << "/2^" << exponent << ")";
+    
+    PrintNumericalError(Nbits, value, double_approx, "", oconv.str());
+}
+
+
+TestDisplayPowerOfTwoApprox065::TestDisplayPowerOfTwoApprox065(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox035::TestDisplayPowerOfTwoApprox035(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+void TestDisplayPowerOfTwoApprox065::Do(int Nbits) const
+{
+    Display(Nbits, 0.65);
+}
+
+
+void TestDisplayPowerOfTwoApprox035::Do(int Nbits) const
+{
+    Display(Nbits, 0.35);
+}
+
+
+
+/*==================================*/
+// TestDisplaySum
+/*==================================*/
+
+TestDisplaySum::TestDisplaySum(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+void TestDisplaySum::Do(int Nbits) const
+{
+    Display(Nbits, 0.65, 3515, 0.35, 4832);
+}
+
+
+void TestDisplaySum::Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const
+{
+    double exact = std::round(value1 * coefficient1 + value2 * coefficient2);
+
+    PowerOfTwoApprox approx1(Nbits, value1);
+    PowerOfTwoApprox approx2(Nbits, value2);
+
+    int approx = approx1 * coefficient1 + approx2 * coefficient2;
+    
+    std::ostringstream oconv;
+    oconv << value1 << " * " << coefficient1  << " + " << value2 << " * " << coefficient2 << " = ";
+    
+    PrintNumericalError(Nbits, exact, static_cast<double>(approx), oconv.str(), "");
+}
+
+
+/*==================================*/
+// TestDisplayContainer
+/*==================================*/
+
+TestDisplayContainer::TestDisplayContainer(std::size_t size)
+: size_(size)
+{
+    test_display_list_ = new TestDisplay*[size];
+
+    for (auto i = 0ul; i < size; ++i)
+        test_display_list_[i] = nullptr;
+}
+
+
+TestDisplayContainer::~TestDisplayContainer()
+{
+    for (int position = 0; position < next_position_available_; ++position)
+        delete test_display_list_[position];
+    
+    delete[] test_display_list_;
+}
+
+
+void TestDisplayContainer::Register(TestDisplay* test_display)
+{
+    if (next_position_available_ >= static_cast<int>(size_))
+        error("Too many `TestDisplay` registered!");
+    
+    test_display_list_[next_position_available_++] = test_display;
+}
+
+
+int TestDisplayContainer::Nelement() const
+{
+    return next_position_available_;
+}
+
+
+TestDisplay& TestDisplayContainer::GetElement(int i) const
+{
+    if (i < 0 || i >= next_position_available_)
+        error("Invalid index in TestDisplayContainer::GetElement() request!");
+    
+    decltype(auto) element_ptr = test_display_list_[i];
+    return *element_ptr;
+}
+    
+
+
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container)
+{
+    int Nelement = container.Nelement();
+    
+    for (int position = 0; position < Nelement; ++position)
+    {
+        decltype(auto) test_display = container.GetElement(position);
+        
+        for (int Nbits = Nbits_min; Nbits <= Nbits_max; Nbits += Nbits_increment)
+             test_display.Do(Nbits); 
+    
+        std::cout << std::endl;
+    }    
+}
+    
+    
+
diff --git a/3-Operators/TP/Solution/exercice33.cpp b/3-Operators/TP/Solution/exercice33.cpp
new file mode 100644
index 0000000..3944798
--- /dev/null
+++ b/3-Operators/TP/Solution/exercice33.cpp
@@ -0,0 +1,508 @@
+#include <iostream>
+#include <cmath> // for std::round
+#include <string>
+#include <sstream> // for std::ostringstream
+
+
+/************************************/
+// Declarations 
+/************************************/
+
+/*!
+ * \brief  Structure to group together numerator and exponent used to represent a floating-point.
+ * 
+ * Representation is numerator / 2^exponent, where numerator is as large as a selected number of bits make possible.
+ */
+class PowerOfTwoApprox
+{
+public:
+    //! Constructor that compute the best possible approximation of `value` with `Nbits`
+    PowerOfTwoApprox(int Nbits, double value);
+    
+    //! Returns the double value computed from `numerator_` and `exponent_`.
+    explicit operator double() const;
+    
+   /*! 
+    * \brief Multiply the approximate representation by an integer. 
+    * 
+    * \param[in] coefficient Integer coefficient by which the object is multiplied.
+    * 
+    * \return An approximate integer result of the multiplication.
+    */
+    friend int operator*(const PowerOfTwoApprox& approx, int coefficient);
+    
+    friend int operator*(int coefficient, const PowerOfTwoApprox& approx);
+    
+    //! Get the value of the numerator.
+    int Numerator() const;
+    
+    //! Get the value of the exponent.
+    int Exponent() const;
+        
+private:
+    
+    //! Numerator.
+    int numerator_ = 0;
+    
+    //! Exponent applied to the 2 at the denominator.
+    int exponent_ = 0;    
+};
+
+
+
+/*!
+ * \brief Base class for TestDisplayPowerOfTwoApprox and TestDisplaySum.
+ */
+class TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplay(int resolution);
+    
+    //! Virtual method.
+    virtual void Do(int Nbits) const = 0;
+    
+    //! Virtual destructor.
+    virtual ~TestDisplay();
+    
+protected:
+    
+   /*!
+    * \brief  Print a line with information about error.
+    *
+    * \param[in] after_bit_string String that might appear
+    */
+   void PrintNumericalError(int Nbits, double exact, double approx,
+                            std::string after_bit_string, std::string before_error) const;
+                              
+    
+private:
+    
+    //! Maximum error index.
+    const int resolution_;
+
+};
+
+
+
+/*!
+ * \brief Class in charge of displaying the approximation for PowerOfTwoApprox for a value which is expected
+ * to be provided in a derived class.
+ */
+class TestDisplayPowerOfTwoApprox : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox(int resolution);
+    
+    //! Virtual destructor.
+    virtual ~TestDisplayPowerOfTwoApprox();
+    
+protected:
+    
+    //! Print the output for `value` when `Nbits` are available.
+    void Display(int Nbits, double value) const;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.65
+class TestDisplayPowerOfTwoApprox065 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox065(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.35
+class TestDisplayPowerOfTwoApprox035 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox035(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+    
+    
+
+/*!
+ * \brief Class in charge of displaying the approximation for 0.65 * 3515 + 0.35 * 4832.
+
+ */
+class TestDisplaySum : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplaySum(int resolution);
+    
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+    
+private:
+    
+    //! Print the output for the approximation of the sum value1 * coefficient1 + value2 * coefficient2.
+    void Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const;
+
+};
+
+
+//! Returns `number` * (2 ^ `exponent`) 
+int times_power_of_2(int number, int exponent);
+
+
+//! Round to `x` the nearest integer.
+int round_as_int(double x);
+
+
+//! Maximum integer that might be represented with `Nbits` bits.
+int max_int(int Nbits);
+
+
+//! Function to call when an error occurred; its aborts the program.
+[[noreturn]] void error(std::string explanation);
+
+
+//! Class which stores several `TestDisplay` as pointers.
+class TestDisplayContainer
+{
+public:
+    
+    //! Constructor.
+    TestDisplayContainer(std::size_t size);
+    
+    //! Destructor.
+    ~TestDisplayContainer();
+        
+    //! Insert a new `TestDisplay` object at the `next_position_available_`.
+    void Register(TestDisplay* test_display);
+    
+    //! Returns the number of registered elements.
+    int Nelement() const;
+    
+    //! Provide access to the `i`-th element.
+    TestDisplay& GetElement(int i) const;
+
+private:
+    
+    //! Store `TestDisplay` objects upon which the display will be called.
+    TestDisplay** test_display_list_;
+    
+    //! Size of the array.
+    const std::size_t size_ = 0;
+
+    //! Position in which the next `TestDisplay` will be put.
+    int next_position_available_ = 0;
+};
+
+
+//! Loop over the content of `TestDisplayContainer`.
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container);
+
+
+/************************************/
+// Main function
+/************************************/
+
+int main(int argc, char** argv)
+{
+    static_cast<void>(argc); // to silence warning about unused argc - don't bother 
+    static_cast<void>(argv); // to silence warning about unused argv - don't bother 
+        
+    TestDisplayContainer container(3);
+    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
+    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
+    container.Register(new TestDisplaySum(1000000));
+    
+    loop(4, 16, 4, container);
+
+    return EXIT_SUCCESS;
+}
+
+
+/************************************/
+// Definitions
+/************************************/
+
+
+int times_power_of_2(int number, int exponent)
+{
+    while (exponent > 0)
+    { 
+        number *= 2; 
+        exponent -= 1; 
+    }
+    while (exponent < 0)
+    { 
+        number /= 2;
+        exponent += 1 ; 
+    }
+    
+    return number;
+}
+
+
+int round_as_int(double x)
+{
+    return static_cast<int>(std::round(x));
+}
+
+
+int max_int(int Nbits)
+{ 
+    return (times_power_of_2(1, Nbits) - 1);
+}
+
+
+[[noreturn]] void error(std::string explanation)
+{
+    std::cout << "ERROR: " << explanation << std::endl;
+    exit(EXIT_FAILURE);
+}
+
+
+/*==================================*/
+// PowerOfTwoApprox
+/*==================================*/
+
+PowerOfTwoApprox::PowerOfTwoApprox(int Nbits, double value)
+{
+    auto& numerator = numerator_;
+    auto& exponent = exponent_;
+    
+    numerator = exponent = 0;
+    int denominator {};
+    
+    int max_numerator = max_int(Nbits);
+    
+    do
+    {
+        ++exponent;
+        denominator = times_power_of_2(1, exponent);   
+        numerator = round_as_int(value * denominator);
+    }
+    while (numerator <= max_numerator);
+    
+    --exponent;
+    denominator = times_power_of_2(1, exponent); 
+    numerator = round_as_int(value * denominator);
+}
+
+
+PowerOfTwoApprox::operator double() const
+{
+    int denominator = times_power_of_2(1, exponent_); 
+    return static_cast<double>(numerator_) / denominator;
+}
+
+
+int PowerOfTwoApprox::Numerator() const
+{
+    return numerator_;
+}
+
+
+int PowerOfTwoApprox::Exponent() const
+{
+    return exponent_;
+}
+
+
+int operator*(const PowerOfTwoApprox& approx, int coefficient)
+{
+    return times_power_of_2(approx.Numerator() * coefficient, -approx.Exponent());
+}
+
+
+int operator*(int coefficient, const PowerOfTwoApprox& approx)
+{
+    return approx * coefficient;
+}
+
+
+/*==================================*/
+// TestDisplay
+/*==================================*/
+
+TestDisplay::TestDisplay(int resolution)
+: resolution_(resolution)
+{ }
+
+
+TestDisplay::~TestDisplay() = default;
+
+
+void TestDisplay::PrintNumericalError(int Nbits, double exact, double approx,
+                                      std::string after_bit_string, std::string before_error) const
+{
+    int error = round_as_int(resolution_ * std::fabs(exact - approx) / exact);
+    
+    std::cout << "[With " << Nbits << " bits]: " << after_bit_string
+        << exact << " ~ " << approx
+        << before_error
+        << "  [error = " << error << "/" << resolution_ << "]" 
+        << std::endl;    
+}
+
+
+/*==================================*/
+// TestDisplayPowerOfTwoApprox
+/*==================================*/
+
+TestDisplayPowerOfTwoApprox::TestDisplayPowerOfTwoApprox(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox::~TestDisplayPowerOfTwoApprox() = default;
+
+
+void TestDisplayPowerOfTwoApprox::Display(int Nbits, double value) const
+{
+    PowerOfTwoApprox approx(Nbits, value);
+    
+    auto numerator = approx.Numerator();
+    auto exponent = approx.Exponent();
+
+    double double_approx = static_cast<double>(approx);
+    
+    std::ostringstream oconv;
+    oconv << "  (" << numerator << "/2^" << exponent << ")";
+    
+    PrintNumericalError(Nbits, value, double_approx, "", oconv.str());
+}
+
+
+TestDisplayPowerOfTwoApprox065::TestDisplayPowerOfTwoApprox065(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox035::TestDisplayPowerOfTwoApprox035(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+void TestDisplayPowerOfTwoApprox065::Do(int Nbits) const
+{
+    Display(Nbits, 0.65);
+}
+
+
+void TestDisplayPowerOfTwoApprox035::Do(int Nbits) const
+{
+    Display(Nbits, 0.35);
+}
+
+
+
+/*==================================*/
+// TestDisplaySum
+/*==================================*/
+
+TestDisplaySum::TestDisplaySum(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+void TestDisplaySum::Do(int Nbits) const
+{
+    Display(Nbits, 0.65, 3515, 0.35, 4832);
+}
+
+
+void TestDisplaySum::Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const
+{
+    double exact = std::round(value1 * coefficient1 + value2 * coefficient2);
+
+    PowerOfTwoApprox approx1(Nbits, value1);
+    PowerOfTwoApprox approx2(Nbits, value2);
+
+    int approx = coefficient1 * approx1 + coefficient2 * approx2;
+        
+    std::ostringstream oconv;
+    oconv << value1 << " * " << coefficient1  << " + " << value2 << " * " << coefficient2 << " = ";
+    
+    PrintNumericalError(Nbits, exact, static_cast<double>(approx), oconv.str(), "");
+}
+
+
+/*==================================*/
+// TestDisplayContainer
+/*==================================*/
+
+TestDisplayContainer::TestDisplayContainer(std::size_t size)
+: size_(size)
+{
+    test_display_list_ = new TestDisplay*[size];
+
+    for (auto i = 0ul; i < size; ++i)
+        test_display_list_[i] = nullptr;
+}
+
+
+TestDisplayContainer::~TestDisplayContainer()
+{
+    for (int position = 0; position < next_position_available_; ++position)
+        delete test_display_list_[position];
+    
+    delete[] test_display_list_;
+}
+
+
+void TestDisplayContainer::Register(TestDisplay* test_display)
+{
+    if (next_position_available_ >= static_cast<int>(size_))
+        error("Too many `TestDisplay` registered!");
+    
+    test_display_list_[next_position_available_++] = test_display;
+}
+
+
+int TestDisplayContainer::Nelement() const
+{
+    return next_position_available_;
+}
+
+
+TestDisplay& TestDisplayContainer::GetElement(int i) const
+{
+    if (i < 0 || i >= next_position_available_)
+        error("Invalid index in TestDisplayContainer::GetElement() request!");
+    
+    decltype(auto) element_ptr = test_display_list_[i];
+    return *element_ptr;
+}
+    
+
+
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container)
+{
+    int Nelement = container.Nelement();
+    
+    for (int position = 0; position < Nelement; ++position)
+    {
+        decltype(auto) test_display = container.GetElement(position);
+        
+        for (int Nbits = Nbits_min; Nbits <= Nbits_max; Nbits += Nbits_increment)
+             test_display.Do(Nbits); 
+    
+        std::cout << std::endl;
+    }    
+}
+    
+    
+
diff --git a/3-Operators/TP/Solution/exercice34.cpp b/3-Operators/TP/Solution/exercice34.cpp
new file mode 100644
index 0000000..0329a22
--- /dev/null
+++ b/3-Operators/TP/Solution/exercice34.cpp
@@ -0,0 +1,508 @@
+#include <iostream>
+#include <cmath> // for std::round
+#include <string>
+#include <sstream> // for std::ostringstream
+
+
+/************************************/
+// Declarations 
+/************************************/
+
+/*!
+ * \brief  Structure to group together numerator and exponent used to represent a floating-point.
+ * 
+ * Representation is numerator / 2^exponent, where numerator is as large as a selected number of bits make possible.
+ */
+class PowerOfTwoApprox
+{
+public:
+    //! Constructor that compute the best possible approximation of `value` with `Nbits`
+    PowerOfTwoApprox(int Nbits, double value);
+    
+    //! Returns the double value computed from `numerator_` and `exponent_`.
+    explicit operator double() const;
+    
+   /*! 
+    * \brief Multiply the approximate representation by an integer. 
+    * 
+    * \param[in] coefficient Integer coefficient by which the object is multiplied.
+    * 
+    * \return An approximate integer result of the multiplication.
+    */
+    friend int operator*(const PowerOfTwoApprox& approx, int coefficient);
+    
+    friend int operator*(int coefficient, const PowerOfTwoApprox& approx);
+    
+    //! Get the value of the numerator.
+    int Numerator() const;
+    
+    //! Get the value of the exponent.
+    int Exponent() const;
+        
+private:
+    
+    //! Numerator.
+    int numerator_ = 0;
+    
+    //! Exponent applied to the 2 at the denominator.
+    int exponent_ = 0;    
+};
+
+
+
+/*!
+ * \brief Base class for TestDisplayPowerOfTwoApprox and TestDisplaySum.
+ */
+class TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplay(int resolution);
+    
+    //! Virtual method.
+    virtual void Do(int Nbits) const = 0;
+    
+    //! Virtual destructor.
+    virtual ~TestDisplay();
+    
+protected:
+    
+   /*!
+    * \brief  Print a line with information about error.
+    *
+    * \param[in] after_bit_string String that might appear
+    */
+   void PrintNumericalError(int Nbits, double exact, double approx,
+                            std::string after_bit_string, std::string before_error) const;
+                              
+    
+private:
+    
+    //! Maximum error index.
+    const int resolution_;
+
+};
+
+
+
+/*!
+ * \brief Class in charge of displaying the approximation for PowerOfTwoApprox for a value which is expected
+ * to be provided in a derived class.
+ */
+class TestDisplayPowerOfTwoApprox : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox(int resolution);
+    
+    //! Virtual destructor.
+    virtual ~TestDisplayPowerOfTwoApprox();
+    
+protected:
+    
+    //! Print the output for `value` when `Nbits` are available.
+    void Display(int Nbits, double value) const;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.65
+class TestDisplayPowerOfTwoApprox065 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox065(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.35
+class TestDisplayPowerOfTwoApprox035 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox035(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+    
+    
+
+/*!
+ * \brief Class in charge of displaying the approximation for 0.65 * 3515 + 0.35 * 4832.
+
+ */
+class TestDisplaySum : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplaySum(int resolution);
+    
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+    
+private:
+    
+    //! Print the output for the approximation of the sum value1 * coefficient1 + value2 * coefficient2.
+    void Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const;
+
+};
+
+
+//! Returns `number` * (2 ^ `exponent`) 
+int times_power_of_2(int number, int exponent);
+
+
+//! Round to `x` the nearest integer.
+int round_as_int(double x);
+
+
+//! Maximum integer that might be represented with `Nbits` bits.
+int max_int(int Nbits);
+
+
+//! Function to call when an error occurred; its aborts the program.
+[[noreturn]] void error(std::string explanation);
+
+
+//! Class which stores several `TestDisplay` as pointers.
+class TestDisplayContainer
+{
+public:
+    
+    //! Constructor.
+    TestDisplayContainer(std::size_t size);
+    
+    //! Destructor.
+    ~TestDisplayContainer();
+        
+    //! Insert a new `TestDisplay` object at the `next_position_available_`.
+    void Register(TestDisplay* test_display);
+    
+    //! Returns the number of registered elements.
+    int Nelement() const;
+    
+    //! Provide access to the `i`-th element.
+    TestDisplay& operator[](int i) const;
+
+private:
+    
+    //! Store `TestDisplay` objects upon which the display will be called.
+    TestDisplay** test_display_list_;
+    
+    //! Size of the array.
+    const std::size_t size_ = 0;
+
+    //! Position in which the next `TestDisplay` will be put.
+    int next_position_available_ = 0;
+};
+
+
+//! Loop over the content of `TestDisplayContainer`.
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container);
+
+
+/************************************/
+// Main function
+/************************************/
+
+int main(int argc, char** argv)
+{
+    static_cast<void>(argc); // to silence warning about unused argc - don't bother 
+    static_cast<void>(argv); // to silence warning about unused argv - don't bother 
+        
+    TestDisplayContainer container(3);
+    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
+    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
+    container.Register(new TestDisplaySum(1000000));
+    
+    loop(4, 16, 4, container);
+
+    return EXIT_SUCCESS;
+}
+
+
+/************************************/
+// Definitions
+/************************************/
+
+
+int times_power_of_2(int number, int exponent)
+{
+    while (exponent > 0)
+    { 
+        number *= 2; 
+        exponent -= 1; 
+    }
+    while (exponent < 0)
+    { 
+        number /= 2;
+        exponent += 1 ; 
+    }
+    
+    return number;
+}
+
+
+int round_as_int(double x)
+{
+    return static_cast<int>(std::round(x));
+}
+
+
+int max_int(int Nbits)
+{ 
+    return (times_power_of_2(1, Nbits) - 1);
+}
+
+
+[[noreturn]] void error(std::string explanation)
+{
+    std::cout << "ERROR: " << explanation << std::endl;
+    exit(EXIT_FAILURE);
+}
+
+
+/*==================================*/
+// PowerOfTwoApprox
+/*==================================*/
+
+PowerOfTwoApprox::PowerOfTwoApprox(int Nbits, double value)
+{
+    auto& numerator = numerator_;
+    auto& exponent = exponent_;
+    
+    numerator = exponent = 0;
+    int denominator {};
+    
+    int max_numerator = max_int(Nbits);
+    
+    do
+    {
+        ++exponent;
+        denominator = times_power_of_2(1, exponent);   
+        numerator = round_as_int(value * denominator);
+    }
+    while (numerator <= max_numerator);
+    
+    --exponent;
+    denominator = times_power_of_2(1, exponent); 
+    numerator = round_as_int(value * denominator);
+}
+
+
+PowerOfTwoApprox::operator double() const
+{
+    int denominator = times_power_of_2(1, exponent_); 
+    return static_cast<double>(numerator_) / denominator;
+}
+
+
+int PowerOfTwoApprox::Numerator() const
+{
+    return numerator_;
+}
+
+
+int PowerOfTwoApprox::Exponent() const
+{
+    return exponent_;
+}
+
+
+int operator*(const PowerOfTwoApprox& approx, int coefficient)
+{
+    return times_power_of_2(approx.Numerator() * coefficient, -approx.Exponent());
+}
+
+
+int operator*(int coefficient, const PowerOfTwoApprox& approx)
+{
+    return approx * coefficient;
+}
+
+
+/*==================================*/
+// TestDisplay
+/*==================================*/
+
+TestDisplay::TestDisplay(int resolution)
+: resolution_(resolution)
+{ }
+
+
+TestDisplay::~TestDisplay() = default;
+
+
+void TestDisplay::PrintNumericalError(int Nbits, double exact, double approx,
+                                      std::string after_bit_string, std::string before_error) const
+{
+    int error = round_as_int(resolution_ * std::fabs(exact - approx) / exact);
+    
+    std::cout << "[With " << Nbits << " bits]: " << after_bit_string
+        << exact << " ~ " << approx
+        << before_error
+        << "  [error = " << error << "/" << resolution_ << "]" 
+        << std::endl;    
+}
+
+
+/*==================================*/
+// TestDisplayPowerOfTwoApprox
+/*==================================*/
+
+TestDisplayPowerOfTwoApprox::TestDisplayPowerOfTwoApprox(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox::~TestDisplayPowerOfTwoApprox() = default;
+
+
+void TestDisplayPowerOfTwoApprox::Display(int Nbits, double value) const
+{
+    PowerOfTwoApprox approx(Nbits, value);
+    
+    auto numerator = approx.Numerator();
+    auto exponent = approx.Exponent();
+
+    double double_approx = static_cast<double>(approx);
+    
+    std::ostringstream oconv;
+    oconv << "  (" << numerator << "/2^" << exponent << ")";
+    
+    PrintNumericalError(Nbits, value, double_approx, "", oconv.str());
+}
+
+
+TestDisplayPowerOfTwoApprox065::TestDisplayPowerOfTwoApprox065(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox035::TestDisplayPowerOfTwoApprox035(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+void TestDisplayPowerOfTwoApprox065::Do(int Nbits) const
+{
+    Display(Nbits, 0.65);
+}
+
+
+void TestDisplayPowerOfTwoApprox035::Do(int Nbits) const
+{
+    Display(Nbits, 0.35);
+}
+
+
+
+/*==================================*/
+// TestDisplaySum
+/*==================================*/
+
+TestDisplaySum::TestDisplaySum(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+void TestDisplaySum::Do(int Nbits) const
+{
+    Display(Nbits, 0.65, 3515, 0.35, 4832);
+}
+
+
+void TestDisplaySum::Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const
+{
+    double exact = std::round(value1 * coefficient1 + value2 * coefficient2);
+
+    PowerOfTwoApprox approx1(Nbits, value1);
+    PowerOfTwoApprox approx2(Nbits, value2);
+
+    int approx = coefficient1 * approx1 + coefficient2 * approx2;
+        
+    std::ostringstream oconv;
+    oconv << value1 << " * " << coefficient1  << " + " << value2 << " * " << coefficient2 << " = ";
+    
+    PrintNumericalError(Nbits, exact, static_cast<double>(approx), oconv.str(), "");
+}
+
+
+/*==================================*/
+// TestDisplayContainer
+/*==================================*/
+
+TestDisplayContainer::TestDisplayContainer(std::size_t size)
+: size_(size)
+{
+    test_display_list_ = new TestDisplay*[size];
+
+    for (auto i = 0ul; i < size; ++i)
+        test_display_list_[i] = nullptr;
+}
+
+
+TestDisplayContainer::~TestDisplayContainer()
+{
+    for (int position = 0; position < next_position_available_; ++position)
+        delete test_display_list_[position];
+    
+    delete[] test_display_list_;
+}
+
+
+void TestDisplayContainer::Register(TestDisplay* test_display)
+{
+    if (next_position_available_ >= static_cast<int>(size_))
+        error("Too many `TestDisplay` registered!");
+    
+    test_display_list_[next_position_available_++] = test_display;
+}
+
+
+int TestDisplayContainer::Nelement() const
+{
+    return next_position_available_;
+}
+
+
+TestDisplay& TestDisplayContainer::operator[](int i) const
+{
+    if (i < 0 || i >= next_position_available_)
+        error("Invalid index in TestDisplayContainer::operator[] request!");
+    
+    decltype(auto) element_ptr = test_display_list_[i];
+    return *element_ptr;
+}
+    
+
+
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container)
+{
+    int Nelement = container.Nelement();
+    
+    for (int position = 0; position < Nelement; ++position)
+    {
+        decltype(auto) test_display = container[position];
+        
+        for (int Nbits = Nbits_min; Nbits <= Nbits_max; Nbits += Nbits_increment)
+             test_display.Do(Nbits); 
+    
+        std::cout << std::endl;
+    }    
+}
+    
+    
+
diff --git a/3-Operators/TP/Solution/exercice35.cpp b/3-Operators/TP/Solution/exercice35.cpp
new file mode 100644
index 0000000..d5c88d0
--- /dev/null
+++ b/3-Operators/TP/Solution/exercice35.cpp
@@ -0,0 +1,529 @@
+#include <iostream>
+#include <cmath> // for std::round
+#include <string>
+#include <sstream> // for std::ostringstream
+
+
+/************************************/
+// Declarations 
+/************************************/
+
+/*!
+ * \brief  Structure to group together numerator and exponent used to represent a floating-point.
+ * 
+ * Representation is numerator / 2^exponent, where numerator is as large as a selected number of bits make possible.
+ */
+class PowerOfTwoApprox
+{
+public:
+    //! Constructor that compute the best possible approximation of `value` with `Nbits`
+    PowerOfTwoApprox(int Nbits, double value);
+    
+    //! Returns the double value computed from `numerator_` and `exponent_`.
+    explicit operator double() const;
+    
+   /*! 
+    * \brief Multiply the approximate representation by an integer. 
+    * 
+    * \param[in] coefficient Integer coefficient by which the object is multiplied.
+    * 
+    * \return An approximate integer result of the multiplication.
+    */
+    friend int operator*(const PowerOfTwoApprox& approx, int coefficient);
+    
+    friend int operator*(int coefficient, const PowerOfTwoApprox& approx);
+    
+    //! Get the value of the numerator.
+    int Numerator() const;
+    
+    //! Get the value of the exponent.
+    int Exponent() const;
+        
+private:
+    
+    //! Numerator.
+    int numerator_ = 0;
+    
+    //! Exponent applied to the 2 at the denominator.
+    int exponent_ = 0;    
+};
+
+
+namespace std
+{
+    
+    
+    std::ostream& operator<<(std::ostream& out, const PowerOfTwoApprox& approx);
+
+
+} // namespace std
+
+
+
+/*!
+ * \brief Base class for TestDisplayPowerOfTwoApprox and TestDisplaySum.
+ */
+class TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplay(int resolution);
+    
+    //! Virtual method.
+    virtual void Do(int Nbits) const = 0;
+    
+    //! Virtual destructor.
+    virtual ~TestDisplay();
+    
+protected:
+    
+   /*!
+    * \brief  Print a line with information about error.
+    *
+    * \param[in] after_bit_string String that might appear
+    */
+   void PrintNumericalError(int Nbits, double exact, double approx,
+                            std::string after_bit_string, std::string before_error) const;
+                              
+    
+private:
+    
+    //! Maximum error index.
+    const int resolution_;
+
+};
+
+
+
+/*!
+ * \brief Class in charge of displaying the approximation for PowerOfTwoApprox for a value which is expected
+ * to be provided in a derived class.
+ */
+class TestDisplayPowerOfTwoApprox : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox(int resolution);
+    
+    //! Virtual destructor.
+    virtual ~TestDisplayPowerOfTwoApprox();
+    
+protected:
+    
+    //! Print the output for `value` when `Nbits` are available.
+    void Display(int Nbits, double value) const;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.65
+class TestDisplayPowerOfTwoApprox065 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox065(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.35
+class TestDisplayPowerOfTwoApprox035 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox035(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+    
+    
+
+/*!
+ * \brief Class in charge of displaying the approximation for 0.65 * 3515 + 0.35 * 4832.
+
+ */
+class TestDisplaySum : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplaySum(int resolution);
+    
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+    
+private:
+    
+    //! Print the output for the approximation of the sum value1 * coefficient1 + value2 * coefficient2.
+    void Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const;
+
+};
+
+
+//! Returns `number` * (2 ^ `exponent`) 
+int times_power_of_2(int number, int exponent);
+
+
+//! Round to `x` the nearest integer.
+int round_as_int(double x);
+
+
+//! Maximum integer that might be represented with `Nbits` bits.
+int max_int(int Nbits);
+
+
+//! Function to call when an error occurred; its aborts the program.
+[[noreturn]] void error(std::string explanation);
+
+
+//! Class which stores several `TestDisplay` as pointers.
+class TestDisplayContainer
+{
+public:
+    
+    //! Constructor.
+    TestDisplayContainer(std::size_t size);
+    
+    //! Destructor.
+    ~TestDisplayContainer();
+        
+    //! Insert a new `TestDisplay` object at the `next_position_available_`.
+    void Register(TestDisplay* test_display);
+    
+    //! Returns the number of registered elements.
+    int Nelement() const;
+    
+    //! Provide access to the `i`-th element.
+    TestDisplay& operator[](int i) const;
+
+private:
+    
+    //! Store `TestDisplay` objects upon which the display will be called.
+    TestDisplay** test_display_list_;
+    
+    //! Size of the array.
+    const std::size_t size_ = 0;
+
+    //! Position in which the next `TestDisplay` will be put.
+    int next_position_available_ = 0;
+};
+
+
+//! Loop over the content of `TestDisplayContainer`.
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container);
+
+
+/************************************/
+// Main function
+/************************************/
+
+int main(int argc, char** argv)
+{
+    static_cast<void>(argc); // to silence warning about unused argc - don't bother 
+    static_cast<void>(argv); // to silence warning about unused argv - don't bother 
+        
+    TestDisplayContainer container(3);
+    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
+    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
+    container.Register(new TestDisplaySum(1000000));
+    
+    loop(4, 16, 4, container);
+
+    return EXIT_SUCCESS;
+}
+
+
+/************************************/
+// Definitions
+/************************************/
+
+
+int times_power_of_2(int number, int exponent)
+{
+    while (exponent > 0)
+    { 
+        number *= 2; 
+        exponent -= 1; 
+    }
+    while (exponent < 0)
+    { 
+        number /= 2;
+        exponent += 1 ; 
+    }
+    
+    return number;
+}
+
+
+int round_as_int(double x)
+{
+    return static_cast<int>(std::round(x));
+}
+
+
+int max_int(int Nbits)
+{ 
+    return (times_power_of_2(1, Nbits) - 1);
+}
+
+
+[[noreturn]] void error(std::string explanation)
+{
+    std::cout << "ERROR: " << explanation << std::endl;
+    exit(EXIT_FAILURE);
+}
+
+
+/*==================================*/
+// PowerOfTwoApprox
+/*==================================*/
+
+PowerOfTwoApprox::PowerOfTwoApprox(int Nbits, double value)
+{
+    auto& numerator = numerator_;
+    auto& exponent = exponent_;
+    
+    numerator = exponent = 0;
+    int denominator {};
+    
+    int max_numerator = max_int(Nbits);
+    
+    do
+    {
+        ++exponent;
+        denominator = times_power_of_2(1, exponent);   
+        numerator = round_as_int(value * denominator);
+    }
+    while (numerator <= max_numerator);
+    
+    --exponent;
+    denominator = times_power_of_2(1, exponent); 
+    numerator = round_as_int(value * denominator);
+}
+
+
+PowerOfTwoApprox::operator double() const
+{
+    int denominator = times_power_of_2(1, exponent_); 
+    return static_cast<double>(numerator_) / denominator;
+}
+
+
+int PowerOfTwoApprox::Numerator() const
+{
+    return numerator_;
+}
+
+
+int PowerOfTwoApprox::Exponent() const
+{
+    return exponent_;
+}
+
+
+int operator*(const PowerOfTwoApprox& approx, int coefficient)
+{
+    return times_power_of_2(approx.Numerator() * coefficient, -approx.Exponent());
+}
+
+
+int operator*(int coefficient, const PowerOfTwoApprox& approx)
+{
+    return approx * coefficient;
+}
+
+
+/*==================================*/
+// TestDisplay
+/*==================================*/
+
+TestDisplay::TestDisplay(int resolution)
+: resolution_(resolution)
+{ }
+
+
+TestDisplay::~TestDisplay() = default;
+
+
+void TestDisplay::PrintNumericalError(int Nbits, double exact, double approx,
+                                      std::string after_bit_string, std::string before_error) const
+{
+    int error = round_as_int(resolution_ * std::fabs(exact - approx) / exact);
+    
+    std::cout << "[With " << Nbits << " bits]: " << after_bit_string
+        << exact << " ~ " << approx
+        << before_error
+        << "  [error = " << error << "/" << resolution_ << "]" 
+        << std::endl;    
+}
+
+
+/*==================================*/
+// TestDisplayPowerOfTwoApprox
+/*==================================*/
+
+TestDisplayPowerOfTwoApprox::TestDisplayPowerOfTwoApprox(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox::~TestDisplayPowerOfTwoApprox() = default;
+
+
+void TestDisplayPowerOfTwoApprox::Display(int Nbits, double value) const
+{
+    PowerOfTwoApprox approx(Nbits, value);
+    
+    double double_approx = static_cast<double>(approx);
+    
+    std::ostringstream oconv;
+    oconv << "  (" << approx << ')';
+    
+    PrintNumericalError(Nbits, value, double_approx, "", oconv.str());
+}
+
+
+TestDisplayPowerOfTwoApprox065::TestDisplayPowerOfTwoApprox065(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox035::TestDisplayPowerOfTwoApprox035(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+void TestDisplayPowerOfTwoApprox065::Do(int Nbits) const
+{
+    Display(Nbits, 0.65);
+}
+
+
+void TestDisplayPowerOfTwoApprox035::Do(int Nbits) const
+{
+    Display(Nbits, 0.35);
+}
+
+
+
+/*==================================*/
+// TestDisplaySum
+/*==================================*/
+
+TestDisplaySum::TestDisplaySum(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+void TestDisplaySum::Do(int Nbits) const
+{
+    Display(Nbits, 0.65, 3515, 0.35, 4832);
+}
+
+
+void TestDisplaySum::Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const
+{
+    double exact = std::round(value1 * coefficient1 + value2 * coefficient2);
+
+    PowerOfTwoApprox approx1(Nbits, value1);
+    PowerOfTwoApprox approx2(Nbits, value2);
+
+    int approx = coefficient1 * approx1 + coefficient2 * approx2;
+        
+    std::ostringstream oconv;
+    oconv << value1 << " * " << coefficient1  << " + " << value2 << " * " << coefficient2 << " = ";
+    
+    PrintNumericalError(Nbits, exact, static_cast<double>(approx), oconv.str(), "");
+}
+
+
+/*==================================*/
+// TestDisplayContainer
+/*==================================*/
+
+TestDisplayContainer::TestDisplayContainer(std::size_t size)
+: size_(size)
+{
+    test_display_list_ = new TestDisplay*[size];
+
+    for (auto i = 0ul; i < size; ++i)
+        test_display_list_[i] = nullptr;
+}
+
+
+TestDisplayContainer::~TestDisplayContainer()
+{
+    for (int position = 0; position < next_position_available_; ++position)
+        delete test_display_list_[position];
+    
+    delete[] test_display_list_;
+}
+
+
+void TestDisplayContainer::Register(TestDisplay* test_display)
+{
+    if (next_position_available_ >= static_cast<int>(size_))
+        error("Too many `TestDisplay` registered!");
+    
+    test_display_list_[next_position_available_++] = test_display;
+}
+
+
+int TestDisplayContainer::Nelement() const
+{
+    return next_position_available_;
+}
+
+
+TestDisplay& TestDisplayContainer::operator[](int i) const
+{
+    if (i < 0 || i >= next_position_available_)
+        error("Invalid index in TestDisplayContainer::operator[] request!");
+    
+    decltype(auto) element_ptr = test_display_list_[i];
+    return *element_ptr;
+}
+    
+
+
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container)
+{
+    int Nelement = container.Nelement();
+    
+    for (int position = 0; position < Nelement; ++position)
+    {
+        decltype(auto) test_display = container[position];
+        
+        for (int Nbits = Nbits_min; Nbits <= Nbits_max; Nbits += Nbits_increment)
+             test_display.Do(Nbits); 
+    
+        std::cout << std::endl;
+    }    
+}
+
+
+namespace std
+{
+    
+    
+    std::ostream& operator<<(std::ostream& out, const PowerOfTwoApprox& approx)
+    {
+        out << approx.Numerator() << "/2^" << approx.Exponent();
+        return out;
+    }
+
+
+} // namespace std
+    
+    
+
diff --git a/3-Operators/TP/Solution/exercice36.cpp b/3-Operators/TP/Solution/exercice36.cpp
new file mode 100644
index 0000000..778c8a5
--- /dev/null
+++ b/3-Operators/TP/Solution/exercice36.cpp
@@ -0,0 +1,529 @@
+#include <iostream>
+#include <cmath> // for std::round
+#include <string>
+#include <sstream> // for std::ostringstream
+
+
+/************************************/
+// Declarations 
+/************************************/
+
+/*!
+ * \brief  Structure to group together numerator and exponent used to represent a floating-point.
+ * 
+ * Representation is numerator / 2^exponent, where numerator is as large as a selected number of bits make possible.
+ */
+class PowerOfTwoApprox
+{
+public:
+    //! Constructor that compute the best possible approximation of `value` with `Nbits`
+    PowerOfTwoApprox(int Nbits, double value);
+    
+    //! Returns the double value computed from `numerator_` and `exponent_`.
+    explicit operator double() const;
+    
+   /*! 
+    * \brief Multiply the approximate representation by an integer. 
+    * 
+    * \param[in] coefficient Integer coefficient by which the object is multiplied.
+    * 
+    * \return An approximate integer result of the multiplication.
+    */
+    friend int operator*(const PowerOfTwoApprox& approx, int coefficient);
+    
+    friend int operator*(int coefficient, const PowerOfTwoApprox& approx);
+    
+    //! Get the value of the numerator.
+    int Numerator() const;
+    
+    //! Get the value of the exponent.
+    int Exponent() const;
+        
+private:
+    
+    //! Numerator.
+    int numerator_ = 0;
+    
+    //! Exponent applied to the 2 at the denominator.
+    int exponent_ = 0;    
+};
+
+
+namespace std
+{
+    
+    
+    std::ostream& operator<<(std::ostream& out, const PowerOfTwoApprox& approx);
+
+
+} // namespace std
+
+
+
+/*!
+ * \brief Base class for TestDisplayPowerOfTwoApprox and TestDisplaySum.
+ */
+class TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplay(int resolution);
+    
+    //! Virtual method.
+    virtual void operator()(int Nbits) const = 0;
+    
+    //! Virtual destructor.
+    virtual ~TestDisplay();
+    
+protected:
+    
+   /*!
+    * \brief  Print a line with information about error.
+    *
+    * \param[in] after_bit_string String that might appear
+    */
+   void PrintNumericalError(int Nbits, double exact, double approx,
+                            std::string after_bit_string, std::string before_error) const;
+                              
+    
+private:
+    
+    //! Maximum error index.
+    const int resolution_;
+
+};
+
+
+
+/*!
+ * \brief Class in charge of displaying the approximation for PowerOfTwoApprox for a value which is expected
+ * to be provided in a derived class.
+ */
+class TestDisplayPowerOfTwoApprox : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox(int resolution);
+    
+    //! Virtual destructor.
+    virtual ~TestDisplayPowerOfTwoApprox();
+    
+protected:
+    
+    //! Print the output for `value` when `Nbits` are available.
+    void Display(int Nbits, double value) const;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.65
+class TestDisplayPowerOfTwoApprox065 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox065(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void operator()(int Nbits) const override;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.35
+class TestDisplayPowerOfTwoApprox035 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox035(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void operator()(int Nbits) const override;
+
+};
+    
+    
+
+/*!
+ * \brief Class in charge of displaying the approximation for 0.65 * 3515 + 0.35 * 4832.
+
+ */
+class TestDisplaySum : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplaySum(int resolution);
+    
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void operator()(int Nbits) const override;
+    
+private:
+    
+    //! Print the output for the approximation of the sum value1 * coefficient1 + value2 * coefficient2.
+    void Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const;
+
+};
+
+
+//! Returns `number` * (2 ^ `exponent`) 
+int times_power_of_2(int number, int exponent);
+
+
+//! Round to `x` the nearest integer.
+int round_as_int(double x);
+
+
+//! Maximum integer that might be represented with `Nbits` bits.
+int max_int(int Nbits);
+
+
+//! Function to call when an error occurred; its aborts the program.
+[[noreturn]] void error(std::string explanation);
+
+
+//! Class which stores several `TestDisplay` as pointers.
+class TestDisplayContainer
+{
+public:
+    
+    //! Constructor.
+    TestDisplayContainer(std::size_t size);
+    
+    //! Destructor.
+    ~TestDisplayContainer();
+        
+    //! Insert a new `TestDisplay` object at the `next_position_available_`.
+    void Register(TestDisplay* test_display);
+    
+    //! Returns the number of registered elements.
+    int Nelement() const;
+    
+    //! Provide access to the `i`-th element.
+    TestDisplay& operator[](int i) const;
+
+private:
+    
+    //! Store `TestDisplay` objects upon which the display will be called.
+    TestDisplay** test_display_list_;
+    
+    //! Size of the array.
+    const std::size_t size_ = 0;
+
+    //! Position in which the next `TestDisplay` will be put.
+    int next_position_available_ = 0;
+};
+
+
+//! Loop over the content of `TestDisplayContainer`.
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container);
+
+
+/************************************/
+// Main function
+/************************************/
+
+int main(int argc, char** argv)
+{
+    static_cast<void>(argc); // to silence warning about unused argc - don't bother 
+    static_cast<void>(argv); // to silence warning about unused argv - don't bother 
+        
+    TestDisplayContainer container(3);
+    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
+    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
+    container.Register(new TestDisplaySum(1000000));
+    
+    loop(4, 16, 4, container);
+
+    return EXIT_SUCCESS;
+}
+
+
+/************************************/
+// Definitions
+/************************************/
+
+
+int times_power_of_2(int number, int exponent)
+{
+    while (exponent > 0)
+    { 
+        number *= 2; 
+        exponent -= 1; 
+    }
+    while (exponent < 0)
+    { 
+        number /= 2;
+        exponent += 1 ; 
+    }
+    
+    return number;
+}
+
+
+int round_as_int(double x)
+{
+    return static_cast<int>(std::round(x));
+}
+
+
+int max_int(int Nbits)
+{ 
+    return (times_power_of_2(1, Nbits) - 1);
+}
+
+
+[[noreturn]] void error(std::string explanation)
+{
+    std::cout << "ERROR: " << explanation << std::endl;
+    exit(EXIT_FAILURE);
+}
+
+
+/*==================================*/
+// PowerOfTwoApprox
+/*==================================*/
+
+PowerOfTwoApprox::PowerOfTwoApprox(int Nbits, double value)
+{
+    auto& numerator = numerator_;
+    auto& exponent = exponent_;
+    
+    numerator = exponent = 0;
+    int denominator {};
+    
+    int max_numerator = max_int(Nbits);
+    
+    do
+    {
+        ++exponent;
+        denominator = times_power_of_2(1, exponent);   
+        numerator = round_as_int(value * denominator);
+    }
+    while (numerator <= max_numerator);
+    
+    --exponent;
+    denominator = times_power_of_2(1, exponent); 
+    numerator = round_as_int(value * denominator);
+}
+
+
+PowerOfTwoApprox::operator double() const
+{
+    int denominator = times_power_of_2(1, exponent_); 
+    return static_cast<double>(numerator_) / denominator;
+}
+
+
+int PowerOfTwoApprox::Numerator() const
+{
+    return numerator_;
+}
+
+
+int PowerOfTwoApprox::Exponent() const
+{
+    return exponent_;
+}
+
+
+int operator*(const PowerOfTwoApprox& approx, int coefficient)
+{
+    return times_power_of_2(approx.Numerator() * coefficient, -approx.Exponent());
+}
+
+
+int operator*(int coefficient, const PowerOfTwoApprox& approx)
+{
+    return approx * coefficient;
+}
+
+
+/*==================================*/
+// TestDisplay
+/*==================================*/
+
+TestDisplay::TestDisplay(int resolution)
+: resolution_(resolution)
+{ }
+
+
+TestDisplay::~TestDisplay() = default;
+
+
+void TestDisplay::PrintNumericalError(int Nbits, double exact, double approx,
+                                      std::string after_bit_string, std::string before_error) const
+{
+    int error = round_as_int(resolution_ * std::fabs(exact - approx) / exact);
+    
+    std::cout << "[With " << Nbits << " bits]: " << after_bit_string
+        << exact << " ~ " << approx
+        << before_error
+        << "  [error = " << error << "/" << resolution_ << "]" 
+        << std::endl;    
+}
+
+
+/*==================================*/
+// TestDisplayPowerOfTwoApprox
+/*==================================*/
+
+TestDisplayPowerOfTwoApprox::TestDisplayPowerOfTwoApprox(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox::~TestDisplayPowerOfTwoApprox() = default;
+
+
+void TestDisplayPowerOfTwoApprox::Display(int Nbits, double value) const
+{
+    PowerOfTwoApprox approx(Nbits, value);
+    
+    double double_approx = static_cast<double>(approx);
+    
+    std::ostringstream oconv;
+    oconv << "  (" << approx << ')';
+    
+    PrintNumericalError(Nbits, value, double_approx, "", oconv.str());
+}
+
+
+TestDisplayPowerOfTwoApprox065::TestDisplayPowerOfTwoApprox065(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox035::TestDisplayPowerOfTwoApprox035(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+void TestDisplayPowerOfTwoApprox065::operator()(int Nbits) const
+{
+    Display(Nbits, 0.65);
+}
+
+
+void TestDisplayPowerOfTwoApprox035::operator()(int Nbits) const
+{
+    Display(Nbits, 0.35);
+}
+
+
+
+/*==================================*/
+// TestDisplaySum
+/*==================================*/
+
+TestDisplaySum::TestDisplaySum(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+void TestDisplaySum::operator()(int Nbits) const
+{
+    Display(Nbits, 0.65, 3515, 0.35, 4832);
+}
+
+
+void TestDisplaySum::Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const
+{
+    double exact = std::round(value1 * coefficient1 + value2 * coefficient2);
+
+    PowerOfTwoApprox approx1(Nbits, value1);
+    PowerOfTwoApprox approx2(Nbits, value2);
+
+    int approx = coefficient1 * approx1 + coefficient2 * approx2;
+        
+    std::ostringstream oconv;
+    oconv << value1 << " * " << coefficient1  << " + " << value2 << " * " << coefficient2 << " = ";
+    
+    PrintNumericalError(Nbits, exact, static_cast<double>(approx), oconv.str(), "");
+}
+
+
+/*==================================*/
+// TestDisplayContainer
+/*==================================*/
+
+TestDisplayContainer::TestDisplayContainer(std::size_t size)
+: size_(size)
+{
+    test_display_list_ = new TestDisplay*[size];
+
+    for (auto i = 0ul; i < size; ++i)
+        test_display_list_[i] = nullptr;
+}
+
+
+TestDisplayContainer::~TestDisplayContainer()
+{
+    for (int position = 0; position < next_position_available_; ++position)
+        delete test_display_list_[position];
+    
+    delete[] test_display_list_;
+}
+
+
+void TestDisplayContainer::Register(TestDisplay* test_display)
+{
+    if (next_position_available_ >= static_cast<int>(size_))
+        error("Too many `TestDisplay` registered!");
+    
+    test_display_list_[next_position_available_++] = test_display;
+}
+
+
+int TestDisplayContainer::Nelement() const
+{
+    return next_position_available_;
+}
+
+
+TestDisplay& TestDisplayContainer::operator[](int i) const
+{
+    if (i < 0 || i >= next_position_available_)
+        error("Invalid index in TestDisplayContainer::operator[] request!");
+    
+    decltype(auto) element_ptr = test_display_list_[i];
+    return *element_ptr;
+}
+    
+
+
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container)
+{
+    int Nelement = container.Nelement();
+    
+    for (int position = 0; position < Nelement; ++position)
+    {
+        decltype(auto) test_display = container[position];
+        
+        for (int Nbits = Nbits_min; Nbits <= Nbits_max; Nbits += Nbits_increment)
+             test_display(Nbits); 
+    
+        std::cout << std::endl;
+    }    
+}
+
+
+namespace std
+{
+    
+    
+    std::ostream& operator<<(std::ostream& out, const PowerOfTwoApprox& approx)
+    {
+        out << approx.Numerator() << "/2^" << approx.Exponent();
+        return out;
+    }
+
+
+} // namespace std
+    
+    
+
diff --git a/3-Operators/TP/initial_file.cpp b/3-Operators/TP/initial_file.cpp
new file mode 100644
index 0000000..c539ed0
--- /dev/null
+++ b/3-Operators/TP/initial_file.cpp
@@ -0,0 +1,500 @@
+#include <iostream>
+#include <cmath> // for std::round
+#include <string>
+#include <sstream> // for std::ostringstream
+
+
+/************************************/
+// Declarations 
+/************************************/
+
+/*!
+ * \brief  Structure to group together numerator and exponent used to represent a floating-point.
+ * 
+ * Representation is numerator / 2^exponent, where numerator is as large as a selected number of bits make possible.
+ */
+class PowerOfTwoApprox
+{
+public:
+    //! Constructor that compute the best possible approximation of `value` with `Nbits`
+    PowerOfTwoApprox(int Nbits, double value);
+    
+    //! Returns the double value computed from `numerator_` and `exponent_`.
+    double DoubleValue() const;
+    
+   /*! 
+    * \brief Multiply the approximate representation by an integer. 
+    * 
+    * \param[in] coefficient Integer coefficient by which the object is multiplied.
+    * 
+    * \return An approximate integer result of the multiplication.
+    */
+    int Multiply(int coefficient);
+    
+    //! Get the value of the numerator.
+    int Numerator() const;
+    
+    //! Get the value of the exponent.
+    int Exponent() const;
+        
+private:
+    
+    //! Numerator.
+    int numerator_ = 0;
+    
+    //! Exponent applied to the 2 at the denominator.
+    int exponent_ = 0;    
+};
+
+
+
+/*!
+ * \brief Base class for TestDisplayPowerOfTwoApprox and TestDisplaySum.
+ */
+class TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplay(int resolution);
+    
+    //! Virtual method.
+    virtual void Do(int Nbits) const = 0;
+    
+    //! Virtual destructor.
+    virtual ~TestDisplay();
+    
+protected:
+    
+   /*!
+    * \brief  Print a line with information about error.
+    *
+    * \param[in] after_bit_string String that might appear
+    */
+   void PrintNumericalError(int Nbits, double exact, double approx,
+                            std::string after_bit_string, std::string before_error) const;
+                              
+    
+private:
+    
+    //! Maximum error index.
+    const int resolution_;
+
+};
+
+
+
+/*!
+ * \brief Class in charge of displaying the approximation for PowerOfTwoApprox for a value which is expected
+ * to be provided in a derived class.
+ */
+class TestDisplayPowerOfTwoApprox : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox(int resolution);
+    
+    //! Virtual destructor.
+    virtual ~TestDisplayPowerOfTwoApprox();
+    
+protected:
+    
+    //! Print the output for `value` when `Nbits` are available.
+    void Display(int Nbits, double value) const;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.65
+class TestDisplayPowerOfTwoApprox065 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox065(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+
+
+//! Run TestDisplayPowerOfTwoApprox for value 0.35
+class TestDisplayPowerOfTwoApprox035 : public TestDisplayPowerOfTwoApprox
+{
+public:
+    
+    //! Constructor.
+    TestDisplayPowerOfTwoApprox035(int resolution);
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const override;
+
+};
+    
+    
+
+/*!
+ * \brief Class in charge of displaying the approximation for 0.65 * 3515 + 0.35 * 4832.
+
+ */
+class TestDisplaySum : public TestDisplay
+{
+public:
+    
+    //! Constructor.
+    TestDisplaySum(int resolution);
+    
+    
+    //! Print the output for the values 0.65 and 0.35.
+    void Do(int Nbits) const;
+    
+private:
+    
+    //! Print the output for the approximation of the sum value1 * coefficient1 + value2 * coefficient2.
+    void Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const;
+
+};
+
+
+//! Returns `number` * (2 ^ `exponent`) 
+int times_power_of_2(int number, int exponent);
+
+
+//! Round to `x` the nearest integer.
+int round_as_int(double x);
+
+
+//! Maximum integer that might be represented with `Nbits` bits.
+int max_int(int Nbits);
+
+
+//! Function to call when an error occurred; its aborts the program.
+[[noreturn]] void error(std::string explanation);
+
+
+//! Class which stores several `TestDisplay` as pointers.
+class TestDisplayContainer
+{
+public:
+    
+    //! Constructor.
+    TestDisplayContainer(std::size_t size);
+    
+    //! Destructor.
+    ~TestDisplayContainer();
+        
+    //! Insert a new `TestDisplay` object at the `next_position_available_`.
+    void Register(TestDisplay* test_display);
+    
+    //! Returns the number of registered elements.
+    int Nelement() const;
+    
+    //! Provide access to the `i`-th element.
+    TestDisplay& GetElement(int i) const;
+
+private:
+    
+    //! Store `TestDisplay` objects upon which the display will be called.
+    TestDisplay** test_display_list_;
+    
+    //! Size of the array.
+    const std::size_t size_ = 0;
+
+    //! Position in which the next `TestDisplay` will be put.
+    int next_position_available_ = 0;
+};
+
+
+//! Loop over the content of `TestDisplayContainer`.
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container);
+
+
+/************************************/
+// Main function
+/************************************/
+
+int main(int argc, char** argv)
+{
+    static_cast<void>(argc); // to silence warning about unused argc - don't bother 
+    static_cast<void>(argv); // to silence warning about unused argv - don't bother 
+        
+    TestDisplayContainer container(3);
+    container.Register(new TestDisplayPowerOfTwoApprox065(1000000));
+    container.Register(new TestDisplayPowerOfTwoApprox035(1000000));
+    container.Register(new TestDisplaySum(1000000));
+    
+    loop(4, 16, 4, container);
+
+    return EXIT_SUCCESS;
+}
+
+
+/************************************/
+// Definitions
+/************************************/
+
+
+int times_power_of_2(int number, int exponent)
+{
+    while (exponent > 0)
+    { 
+        number *= 2; 
+        exponent -= 1; 
+    }
+    while (exponent < 0)
+    { 
+        number /= 2;
+        exponent += 1 ; 
+    }
+    
+    return number;
+}
+
+
+int round_as_int(double x)
+{
+    return static_cast<int>(std::round(x));
+}
+
+
+int max_int(int Nbits)
+{ 
+    return (times_power_of_2(1, Nbits) - 1);
+}
+
+
+[[noreturn]] void error(std::string explanation)
+{
+    std::cout << "ERROR: " << explanation << std::endl;
+    exit(EXIT_FAILURE);
+}
+
+
+/*==================================*/
+// PowerOfTwoApprox
+/*==================================*/
+
+PowerOfTwoApprox::PowerOfTwoApprox(int Nbits, double value)
+{
+    auto& numerator = numerator_;
+    auto& exponent = exponent_;
+    
+    numerator = exponent = 0;
+    int denominator {};
+    
+    int max_numerator = max_int(Nbits);
+    
+    do
+    {
+        ++exponent;
+        denominator = times_power_of_2(1, exponent);   
+        numerator = round_as_int(value * denominator);
+    }
+    while (numerator <= max_numerator);
+    
+    --exponent;
+    denominator = times_power_of_2(1, exponent); 
+    numerator = round_as_int(value * denominator);
+}
+
+
+double PowerOfTwoApprox::DoubleValue() const
+{
+    int denominator = times_power_of_2(1, exponent_); 
+    return static_cast<double>(numerator_) / denominator;
+}
+
+
+int PowerOfTwoApprox::Numerator() const
+{
+    return numerator_;
+}
+
+
+int PowerOfTwoApprox::Exponent() const
+{
+    return exponent_;
+}
+
+
+int PowerOfTwoApprox::Multiply(int coefficient)
+{
+    return times_power_of_2(Numerator() * coefficient, -Exponent());
+}
+
+
+/*==================================*/
+// TestDisplay
+/*==================================*/
+
+TestDisplay::TestDisplay(int resolution)
+: resolution_(resolution)
+{ }
+
+
+TestDisplay::~TestDisplay() = default;
+
+
+void TestDisplay::PrintNumericalError(int Nbits, double exact, double approx,
+                                      std::string after_bit_string, std::string before_error) const
+{
+    int error = round_as_int(resolution_ * std::fabs(exact - approx) / exact);
+    
+    std::cout << "[With " << Nbits << " bits]: " << after_bit_string
+        << exact << " ~ " << approx
+        << before_error
+        << "  [error = " << error << "/" << resolution_ << "]" 
+        << std::endl;    
+}
+
+
+/*==================================*/
+// TestDisplayPowerOfTwoApprox
+/*==================================*/
+
+TestDisplayPowerOfTwoApprox::TestDisplayPowerOfTwoApprox(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox::~TestDisplayPowerOfTwoApprox() = default;
+
+
+void TestDisplayPowerOfTwoApprox::Display(int Nbits, double value) const
+{
+    PowerOfTwoApprox approx(Nbits, value);
+    
+    auto numerator = approx.Numerator();
+    auto exponent = approx.Exponent();
+
+    double double_approx = approx.DoubleValue();
+    
+    std::ostringstream oconv;
+    oconv << "  (" << numerator << "/2^" << exponent << ")";
+    
+    PrintNumericalError(Nbits, value, double_approx, "", oconv.str());
+}
+
+
+TestDisplayPowerOfTwoApprox065::TestDisplayPowerOfTwoApprox065(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+TestDisplayPowerOfTwoApprox035::TestDisplayPowerOfTwoApprox035(int resolution)
+: TestDisplayPowerOfTwoApprox(resolution)
+{ }
+
+
+void TestDisplayPowerOfTwoApprox065::Do(int Nbits) const
+{
+    Display(Nbits, 0.65);
+}
+
+
+void TestDisplayPowerOfTwoApprox035::Do(int Nbits) const
+{
+    Display(Nbits, 0.35);
+}
+
+
+
+/*==================================*/
+// TestDisplaySum
+/*==================================*/
+
+TestDisplaySum::TestDisplaySum(int resolution)
+: TestDisplay(resolution)
+{ }
+
+
+void TestDisplaySum::Do(int Nbits) const
+{
+    Display(Nbits, 0.65, 3515, 0.35, 4832);
+}
+
+
+void TestDisplaySum::Display(int Nbits, double value1, int coefficient1, double value2, int coefficient2) const
+{
+    double exact = std::round(value1 * coefficient1 + value2 * coefficient2);
+
+    PowerOfTwoApprox approx1(Nbits, value1);
+    PowerOfTwoApprox approx2(Nbits, value2);
+
+    int approx = approx1.Multiply(coefficient1) + approx2.Multiply(coefficient2);
+    
+    std::ostringstream oconv;
+    oconv << value1 << " * " << coefficient1  << " + " << value2 << " * " << coefficient2 << " = ";
+    
+    PrintNumericalError(Nbits, exact, static_cast<double>(approx), oconv.str(), "");
+}
+
+
+/*==================================*/
+// TestDisplayContainer
+/*==================================*/
+
+TestDisplayContainer::TestDisplayContainer(std::size_t size)
+: size_(size)
+{
+    test_display_list_ = new TestDisplay*[size];
+
+    for (auto i = 0ul; i < size; ++i)
+        test_display_list_[i] = nullptr;
+}
+
+
+TestDisplayContainer::~TestDisplayContainer()
+{
+    for (int position = 0; position < next_position_available_; ++position)
+        delete test_display_list_[position];
+    
+    delete[] test_display_list_;
+}
+
+
+void TestDisplayContainer::Register(TestDisplay* test_display)
+{
+    if (next_position_available_ >= static_cast<int>(size_))
+        error("Too many `TestDisplay` registered!");
+    
+    test_display_list_[next_position_available_++] = test_display;
+}
+
+
+int TestDisplayContainer::Nelement() const
+{
+    return next_position_available_;
+}
+
+
+TestDisplay& TestDisplayContainer::GetElement(int i) const
+{
+    if (i < 0 || i >= next_position_available_)
+        error("Invalid index in TestDisplayContainer::GetElement() request!");
+    
+    decltype(auto) element_ptr = test_display_list_[i];
+    return *element_ptr;
+}
+    
+
+
+void loop(int Nbits_min, int Nbits_max, int Nbits_increment, TestDisplayContainer& container)
+{
+    int Nelement = container.Nelement();
+    
+    for (int position = 0; position < Nelement; ++position)
+    {
+        decltype(auto) test_display = container.GetElement(position);
+        
+        for (int Nbits = Nbits_min; Nbits <= Nbits_max; Nbits += Nbits_increment)
+             test_display.Do(Nbits); 
+    
+        std::cout << std::endl;
+    }    
+}
+    
+    
+
diff --git a/5-UsefulConceptsAndSTL/6-SmartPointers.ipynb b/5-UsefulConceptsAndSTL/6-SmartPointers.ipynb
index 6a344bc..ac1ea7b 100644
--- a/5-UsefulConceptsAndSTL/6-SmartPointers.ipynb
+++ b/5-UsefulConceptsAndSTL/6-SmartPointers.ipynb
@@ -96,7 +96,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 1,
    "metadata": {},
    "outputs": [],
    "source": [
diff --git a/6-InRealEnvironment/Docker/ThirdPartyWarning/1-ProblematicCase/CMakeLists.txt b/6-InRealEnvironment/Docker/ThirdPartyWarning/1-ProblematicCase/CMakeLists.txt
index beda9cb..3793468 100644
--- a/6-InRealEnvironment/Docker/ThirdPartyWarning/1-ProblematicCase/CMakeLists.txt
+++ b/6-InRealEnvironment/Docker/ThirdPartyWarning/1-ProblematicCase/CMakeLists.txt
@@ -13,6 +13,13 @@ macro(add_cxx_compiler_flag _flag)
   endif()
 endmacro()
 
+set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ compiler")
+set(CMAKE_C_COMPILER clang CACHE STRING "C compiler")
+set(CMAKE_CXX_STANDARD 17 CACHE INTEGER "Version of the C++ standard to use")
+set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "If ON the GNU version of the standard is used.")
+
+project(GettingStartedWithModernCpp_SimpleBoost)
+
 add_cxx_compiler_flag("-Weverything") # all warnings for clang
 add_cxx_compiler_flag("-Wall") # for gcc (and recognized by clang)
 add_cxx_compiler_flag("-Wextra") # for gcc  (and recognized by clang)
diff --git a/6-InRealEnvironment/Docker/ThirdPartyWarning/2-FixByBuildSystem/CMakeLists.txt b/6-InRealEnvironment/Docker/ThirdPartyWarning/2-FixByBuildSystem/CMakeLists.txt
index db2608d..4e2f7aa 100644
--- a/6-InRealEnvironment/Docker/ThirdPartyWarning/2-FixByBuildSystem/CMakeLists.txt
+++ b/6-InRealEnvironment/Docker/ThirdPartyWarning/2-FixByBuildSystem/CMakeLists.txt
@@ -13,6 +13,14 @@ macro(add_cxx_compiler_flag _flag)
   endif()
 endmacro()
 
+
+set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ compiler")
+set(CMAKE_C_COMPILER clang CACHE STRING "C compiler")
+set(CMAKE_CXX_STANDARD 17 CACHE INTEGER "Version of the C++ standard to use")
+set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "If ON the GNU version of the standard is used.")
+
+project(GettingStartedWithModernCpp_TP_Operators)
+
 add_cxx_compiler_flag("-Weverything") # all warnings for clang
 add_cxx_compiler_flag("-Wall") # for gcc (and recognized by clang)
 add_cxx_compiler_flag("-Wextra") # for gcc  (and recognized by clang)
diff --git a/6-InRealEnvironment/Docker/ThirdPartyWarning/3-FixByPragmas-clang/CMakeLists.txt b/6-InRealEnvironment/Docker/ThirdPartyWarning/3-FixByPragmas-clang/CMakeLists.txt
index beda9cb..0fd6382 100644
--- a/6-InRealEnvironment/Docker/ThirdPartyWarning/3-FixByPragmas-clang/CMakeLists.txt
+++ b/6-InRealEnvironment/Docker/ThirdPartyWarning/3-FixByPragmas-clang/CMakeLists.txt
@@ -13,6 +13,13 @@ macro(add_cxx_compiler_flag _flag)
   endif()
 endmacro()
 
+set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ compiler")
+set(CMAKE_C_COMPILER clang CACHE STRING "C compiler")
+set(CMAKE_CXX_STANDARD 17 CACHE INTEGER "Version of the C++ standard to use")
+set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "If ON the GNU version of the standard is used.")
+
+project(GettingStartedWithModernCpp)
+
 add_cxx_compiler_flag("-Weverything") # all warnings for clang
 add_cxx_compiler_flag("-Wall") # for gcc (and recognized by clang)
 add_cxx_compiler_flag("-Wextra") # for gcc  (and recognized by clang)
diff --git a/6-InRealEnvironment/Docker/ThirdPartyWarning/4-FixByPragmas-clang-gcc/CMakeLists.txt b/6-InRealEnvironment/Docker/ThirdPartyWarning/4-FixByPragmas-clang-gcc/CMakeLists.txt
index beda9cb..0fd6382 100644
--- a/6-InRealEnvironment/Docker/ThirdPartyWarning/4-FixByPragmas-clang-gcc/CMakeLists.txt
+++ b/6-InRealEnvironment/Docker/ThirdPartyWarning/4-FixByPragmas-clang-gcc/CMakeLists.txt
@@ -13,6 +13,13 @@ macro(add_cxx_compiler_flag _flag)
   endif()
 endmacro()
 
+set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ compiler")
+set(CMAKE_C_COMPILER clang CACHE STRING "C compiler")
+set(CMAKE_CXX_STANDARD 17 CACHE INTEGER "Version of the C++ standard to use")
+set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "If ON the GNU version of the standard is used.")
+
+project(GettingStartedWithModernCpp)
+
 add_cxx_compiler_flag("-Weverything") # all warnings for clang
 add_cxx_compiler_flag("-Wall") # for gcc (and recognized by clang)
 add_cxx_compiler_flag("-Wextra") # for gcc  (and recognized by clang)
diff --git a/6-InRealEnvironment/Docker/ThirdPartyWarning/5-FixByPragmas-common/CMakeLists.txt b/6-InRealEnvironment/Docker/ThirdPartyWarning/5-FixByPragmas-common/CMakeLists.txt
index beda9cb..0fd6382 100644
--- a/6-InRealEnvironment/Docker/ThirdPartyWarning/5-FixByPragmas-common/CMakeLists.txt
+++ b/6-InRealEnvironment/Docker/ThirdPartyWarning/5-FixByPragmas-common/CMakeLists.txt
@@ -13,6 +13,13 @@ macro(add_cxx_compiler_flag _flag)
   endif()
 endmacro()
 
+set(CMAKE_CXX_COMPILER clang++ CACHE STRING "C++ compiler")
+set(CMAKE_C_COMPILER clang CACHE STRING "C compiler")
+set(CMAKE_CXX_STANDARD 17 CACHE INTEGER "Version of the C++ standard to use")
+set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "If ON the GNU version of the standard is used.")
+
+project(GettingStartedWithModernCpp)
+
 add_cxx_compiler_flag("-Weverything") # all warnings for clang
 add_cxx_compiler_flag("-Wall") # for gcc (and recognized by clang)
 add_cxx_compiler_flag("-Wextra") # for gcc  (and recognized by clang)
diff --git a/TP/HowTo.ipynb b/TP/HowTo.ipynb
index a1cb1f1..9825c82 100644
--- a/TP/HowTo.ipynb
+++ b/TP/HowTo.ipynb
@@ -85,7 +85,7 @@
     "\n",
     "The steps to compile are the same as presented in the previous section.\n",
     "\n",
-    "For more informations about the Docker way please look the dedicated [README](https://gitlab.inria.fr/formations/cpp/gettingstartedwithmoderncpp/blob/master/TP/README.md).\n"
+    "For more informations about the Docker way please look the dedicated [README](https://gitlab.inria.fr/formations/cpp/gettingstartedwithmoderncpp/blob/master/TP/README.md) (the one within the TP folder of the root directory).\n"
    ]
   },
   {
-- 
GitLab