Commit 7e3575b4 authored by CHAMONT David's avatar CHAMONT David
Browse files

Restart for session of January 2022.

parent 7a4090b2
---
# 1. Basic challenge
## What is displayed ?
......@@ -34,7 +33,6 @@ int main()
* **5**: the famous "most vexing parse" ! `MyInteger mi() ;` is interpreted as a function declaration, not an object construction.
---
# 2. A dynamic memory challenge
## May I copy such an array ?
......@@ -67,7 +65,6 @@ class Array
* *6* : off-topic ; `explicit` is there in order to forbid an implicit compiler conversion between an `unsigned` and an `Array`.
---
# 3. About implicit conversions with predefined numerical types
## What is displayed ?
......@@ -95,7 +92,6 @@ int main()
* **4** : when interpreting `i < j`, the compiler convert all the numbers `unsigned int`, which it considers more accurate than `int`, then the value `-1` becomes the highest possibel value than an `unsigned int` can have, therefore greater than `1`. Damned !
---
# 4. An object-oriented challenge
## What is displayed ?
......@@ -131,7 +127,6 @@ int main()
* **3** : when interpreting `b.m(3.14)`, the compiler find some `m` function within class `B`, and then does not check if the base class has some better matching function.
---
# 5. A floating point challenge
## Why is it returning false ?
......@@ -161,7 +156,6 @@ bool check()
* *4* : nice try ;) actually no, because the step of `1.0` is 2 power 0, it can be exactly encoded in binary basis, and the last value of `index` will exactly be `169.0` ; if the step was `0.1`, for example, the value of ìndex` would never be exactly `169.0`.
---
# 6. A polymorphisme challenge
## What is lacking below ?
......
......@@ -6,7 +6,7 @@
"source": [
"# Demonstration notebook\n",
"\n",
"A jupyter notebook is a sequence of cells. Some of them are for textual explanations, and written in markdown. Some of them are extracts code, and can be executed on the fly, thanks to the associated **kernel** attached to the notebook.\n",
"A jupyter notebook is a sequence of cells. Some of them are for textual explanations, and written in markdown. Other cells are extracts code, and can be executed on the fly, thanks to the associated **kernel** attached to the notebook.\n",
"\n",
"The jupyter notebooks were initially designed for interpreted language, such as python, but the QuantStack company provides the [xeus-cling](https://xeus-cling.readthedocs.io/en/latest/) kernels, which extend those notebooks to C++. This notebook is associated to a C++17 kernel.\n",
"\n",
......
# Get in touch
## Who are the trainers ?
## Breaking the ice
* Helper and translater : [Olga Abramkina](https://discourse.lal.in2p3.fr/u/olga/summary) (CNRS, IDRIS)
* Translater : [Pierre Aubert]() (CNRS, LAPP)
* Main lecturer : [David Chamont](https://discourse.lal.in2p3.fr/u/david/) (CNRS, IJCLab)
* Helper and translater : [Karim Hasnaoui](https://discourse.lal.in2p3.fr/u/hasnaoui/summary) (CNRS, IDRIS)
## Quizz
Live only.
## Who are the trainees ?
* Have you created your account on the [LAL Discourse forum](https://discourse.lal.in2p3.fr/) ?
* Did you fill your profile ? ( Top right / Preferences / Preferences / Profile / About me )
* Do you watch the category [“2021 - Scientific Modern C++”](https://discourse.lal.in2p3.fr/c/formation/2021-scientific-modern-cpp/) ? ( Select the bell on the right )
* Who are the trainers ?
* Quizz
* Who are the trainees ?
* Forum/chat tool
* Git repository
## Exercise
......@@ -59,9 +50,9 @@ int main()
}
```
## How to use notebooks
## How to use C++ notebooks ?
Once jupyter is installed on your machine, do not forget to
Once Jupyter is installed on your machine, do not forget to
add the xeus-cling kernels for C++:
* `conda install -c conda-forge xeus-cling`
......@@ -70,15 +61,17 @@ or the more complete jupyter laboratory :
* `jupyter notebook`
* `jupyter-lab`
The notebooks are files whose name ends with `.ipynb`. Try to read/execute `en.demo.ipynb`.
## If you use Docker
In case you prefer to use Docker, there is a script provided with
the course material, which helps you start a container. Within a
`bash` shell, move to the top folder of *ModernScientificCpp*,
and type :
* `./Etc/docker/run.sh modern gcc10`
* `./Etc/docker/run-8888.sh 4nages default`
Then you can start the old-fashioned server or the laboratory,
Then you can start the old-fashioned server or the jupyter laboratory,
with some few additional options, required for Docker:
* `jupyter notebook --no-browser --allow-root --ip=0.0.0.0`
* `jupyter-lab --no-browser --allow-root --ip=0.0.0.0`
\ No newline at end of file
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Cahier computationnel de démonstration\n",
"\n",
"Un cahier computationnel est une séquence de cellules. Certaines d'entre elles sont destinées à fournir des explications textuelles, et sont écrites en markdown. D'autres sont des extraits de code, et peuvent être exécutées à la volée, grâce au **noyau** associé au cahier.\n",
"\n",
"Les cahiers Jupyter ont été initialement conçus pour des langages interprétés, tels que python, mais la société QuantStack fournit les noyaux [xeus-cling](https://xeus-cling.readthedocs.io/en/latest/), qui étendent ces cahiers au C++. Le cahier présent est associé à un noyau C++17.\n",
"\n",
"Lorsque vous utilisez un cahier, vous pouvez sélectionner interactivement n'importe quelle cellule, *double-cliquer* dessus et modifier son contenu. Ensuite, lorsque vous faites *shift-return*, une cellule markdown sera affichée avec sa mise en page, alors qu'une cellule de code sera exécutée à l'aide du noyau associé."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Code exécuté avec le noyau xeus-cling\n",
"\n",
"Les versions récentes de xeus-cling ont fait d'énormes progrès, afin de marier la nature \"compilée\" du C++ avec la nature \"interprétée\" des cellules des cahiers. Cependant, vous rencontrerez au cours de cette leçon quelques vieux cahiers, avec des astuces qui étaient nécessaires avec les anciens noyaux."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Vous devez considérer que toutes les cellules de code d'un cahier donné sont des sous-ensembles d'un seul grand programme C++. En C++, on ne peut pas déclarer plusieurs fois la même variable. En conséquence, il était initialement impossible de réutiliser le même nom de variable dans plusieurs cellules. Il était même impossible de rejouer plusieurs fois la même cellule ! Afin de contourner cette limite, on enferme souvent chaque cellule dans un bloc `{}`, créant ainsi une portée locale :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"{\n",
" int i = -1 ;\n",
" unsigned int j = 1 ;\n",
" if ( i < j ) std::cout << \"i is less than j\" ;\n",
" else std::cout << \"i is greater than j\" ;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"De plus, jusqu'à récemment, il fallait créer une cellule indépendante pour chaque fonction indépendante, et vous pouvez rencontrer de tels cahiers où nous avons ainsi divisé le code en de nombreuses cellules."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Redémarrer le noyau\n",
"\n",
"Lorsqu'il échoue à compiler un code erroné, le noyau peut passer dans un état *corrompu*, ne pouvant plus rien compiler. Lorsque vous suspectez une telle situation, **redémarrez le noyau** avec le bouton correspondant ci-dessus. Cela peut être fait à tout moment, volontairement, lorsque vous voulez redémarrer votre exécution à partir d'une page blanche."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Code exécuté sur la machine sous-jacente"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Parfois, nous voulons démontrer certaines fonctionnalités modernes du C++ qui ne sont pas encore supportées par le noyau, mais qui peuvent être compilées avec l'ordinateur sur lequel tourne le serveur jupyter. De même, nous avons parfois besoin de bibliothèques supplémentaires qui ne sont pas accessibles au noyau, ou nous voulons diviser notre code en plusieurs fichiers et démontrer comment ces fichiers interagissent."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La cellule ci-dessous, avec sa première ligne \"magique\" `%%file`, va générer un fichier dans le système de fichiers sous-jacent, que vous pouvez voir si vous regardez le navigateur de fichiers à gauche de cette fenêtre, ou si vous lancez un terminal."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%file tmp.ref.cpp\n",
"\n",
"#include <iostream>\n",
"\n",
"template < typename T >\n",
"class Ref\n",
"{\n",
"public :\n",
" Ref( T data ) { data_ = data ; }\n",
" void operator=( T data ) { data_ = data ; }\n",
"private :\n",
" T data_ ;\n",
"} ;\n",
"\n",
"template < typename T >\n",
"Ref<T> make_ref( T & data )\n",
"{ return Ref<T>(data) ; }\n",
"\n",
"template < typename T >\n",
"void f( T data )\n",
"{ data = 42 ; }\n",
"\n",
"int main()\n",
"{\n",
" int i = 0, j = 0 ;\n",
" f(i) ;\n",
" f(make_ref(j)) ;\n",
" std::cout<<i<<\" \"<<j<<std::endl ;\n",
" return 0 ;\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Les cellules ci-dessous, avec leur prompt \"magique\" `!`, exécutent des commandes bash dans le dossier sous-jacent, et affichent leurs sorties."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!rm -f tmp.ref.exe && g++ -std=c++03 tmp.ref.cpp -o tmp.ref.exe"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!./tmp.ref.exe"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "C++17",
"language": "C++17",
"name": "xcpp17"
},
"language_info": {
"codemirror_mode": "text/x-c++src",
"file_extension": ".cpp",
"mimetype": "text/x-c++src",
"name": "c++",
"version": "17"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
<!-- #region -->
# Mise en route
......@@ -5,11 +6,12 @@
Live only.
## Forum
* Création des comptes sur le [forum Discourse du LAL](https://discourse.lal.in2p3.fr/), en remplissant Préférences / Profil.
* Chacun se présente et relis/commente son profil.
* Surveiller la [catégorie 2020 C++ Scientifique Moderne](https://discourse.lal.in2p3.fr/c/formation/Cpp2020).
## Présentations et outils de communication
* Création des comptes sur le [serveur Discord](https://discord.gg/hJEYMcPt).
* Chacun se présente.
## Exercice Ref
......@@ -54,3 +56,4 @@ L'affichage final doit être :
0
42
```
<!-- #endregion -->
......@@ -11,7 +11,8 @@
"* [Numbers](en.1-numbers.ipynb)\n",
"* [Pointeurs](en.2-pointers.ipynb)\n",
"* [Objects](en.3-objects.ipynb)\n",
"* [Templates](en.4-templates.ipynb)"
"* [Templates](en.4-templates.ipynb)\n",
"* [Specialization](en.5-specialization.ipynb)"
]
}
],
......
......@@ -109,7 +109,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"metadata": {
"slideshow": {
"slide_type": "-"
......@@ -123,13 +123,24 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"type\tsizeof()\tmin()\t\tmax()\n",
"int\t4\t\t-2147483648\t2147483647\n",
"float\t4\t\t1.17549e-38\t3.40282e+38\n",
"double\t8\t\t2.22507e-308\t1.79769e+308\n"
]
}
],
"source": [
"std::cout\n",
" << \"type\\tsizeof()\\tmin()\\t\\tmax()\\n\"\n",
......@@ -154,7 +165,23 @@
"source": [
"## Unexpected precision of operations\n",
"\n",
"When compiling an operation, the compiler always favors the type of the operands with the best precision. The `unsigned` types are considered better than their `signed` flavor, and floating point types are considered better than integer types."
"When operations are performed, they are not necessarily performed with the precision of the original variables, but sometimes with a higher one. For example, a `short` based calculation will always be evaluated as an `int`. On the contrary, a `float` based calculation will be evaluated as a `float`... unless an innocent constant of type `double` forces the calculation to `double`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"source": [
"short s = std::numeric_limits<short>::max() ;\n",
"std::cout<<(s+1)<<std::endl ;\n",
"int i = std::numeric_limits<int>::max() ;\n",
"std::cout<<(i+1)<<std::endl ;"
]
},
{
......@@ -165,24 +192,33 @@
}
},
"source": [
"BEWARE: the literal numbers are taken into account. In the example below, the expression `((v1+10)/2)-10` is not evaluated as a `short`, but as an `int`, because the literals involved are of type `int`. Only at the very end, when about to be stored into `v2`, it is truncated into a `short`."
"When an operation mix variables with different precisions, the compiler casts all the operands to the best precision. The `unsigned` types are considered better than their `signed` flavor. Floating point types are considered better than integer types."
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 4,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"sizeof(short) = 2\n",
"sizeof(int) = 4\n",
"32767 => 16378\n"
]
}
],
"source": [
"std::cout<<\"sizeof(short) = \"<<sizeof(short)<<std::endl ;\n",
"std::cout<<\"sizeof(int) = \"<<sizeof(int)<<std::endl ;\n",
"short v1 = std::numeric_limits<short>::max() ;\n",
"short v2 = ((v1+10)/2)-10 ;\n",
"std::cout<<v1<<\" => \"<<v2<<std::endl ;"
"float f = std::numeric_limits<float>::max() ;\n",
"std::cout<<(f*10.f)<<std::endl ;\n",
"std::cout<<(f*10.)<<std::endl ;\n",
"std::cout<<(f*10)<<std::endl ;"
]
},
{
......@@ -222,13 +258,23 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"double 3.1416 => int 3\n",
"long 9223372036854775807 => short -1\n",
"double 1.79769e+308 => float inf\n"
]
}
],
"source": [
"double pi = 3.1416 ;\n",
"int i = pi ;\n",
......@@ -256,13 +302,21 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-23536\n"
]
}
],
"source": [
"void display1( short v )\n",
" { std::cout<<v<<std::endl ; }\n",
......@@ -273,13 +327,21 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"65494\n"
]
}
],
"source": [
"void display2( unsigned short v )\n",
" { std::cout<<v<<std::endl ; }\n",
......@@ -582,7 +644,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {
"slideshow": {
"slide_type": "-"
......@@ -595,7 +657,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"metadata": {
"slideshow": {
"slide_type": "-"
......@@ -922,9 +984,9 @@
"file_extension": ".cpp",
"mimetype": "text/x-c++src",
"name": "c++",
"version": "17"
"version": "14"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
\ No newline at end of file
}
......@@ -923,7 +923,11 @@
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"source": [
"© *CNRS 2020* \n",
"*This document was created by David Chamont and translated by Olga Abramkina. It is available under the [License Creative Commons - Attribution - No commercial use - Shared under the conditions 4.0 International](http://creativecommons.org/licenses/by-nc-sa/4.0/)*"
......
......@@ -7,9 +7,9 @@ ensuite des affres de la manipulation de pointeurs, source numéro un de crash
en C++ comme en C. Puis nous reverrons quelques points avancés et importants
sur la programmation orientée objet.
* [Affaires de nombres](1-nombres.md)
* [Affaires de pointeurs](2-pointeurs.md)
* [Affaires d'objets](3-objets.md)
* [Affaires de nombres](fr.1-nombres.ipynb)
* [Affaires de pointeurs](fr.2-pointeurs.ipynb)
* [Affaires d'objets](fr.3-objets.ipynb)
Nous terminerons ces révisions avec les patrons (templates), l'épouvantail de C++,
mais en même temps ce qui le rend particulièrement puissant aujourd'hui,
......@@ -20,5 +20,5 @@ bibliothèque générique. Par contre, vous en utiliserez beaucoup, écrites par
spécialistes, pendant le cours et après. A ce titre, il est important de savoir
comment cela fonctionne. Accrochez vous bien !
* [Affaires de templates 1/2](4-templates.md)
* [Affaires de templates 2/2](5-specialisation.md)
* [Affaires de templates 1/2](fr.4-templates.ipynb)
* [Affaires de templates 2/2](fr.5-specialisation.ipynb)
......@@ -48,29 +48,32 @@
"outputs": [],
"source": [
"#include <iostream>\n",
"#include <limits>\n",
"\n",
"int main()\n",
" {\n",
" std::cout << \"type\\tsizeof()\\tmin()\\t\\tmax()\\n\\n\" ;\n",
"\n",
" std::cout << \"uchar\\t\"\n",
" << +sizeof(unsigned char) << '\\t' << '\\t'\n",
" << +std::numeric_limits<unsigned char>::min() << '\\t' << '\\t'\n",
" << +std::numeric_limits<unsigned char>::max() << '\\n' ;\n",
" std::cout << \"int\\t\"\n",
" << sizeof(int) << '\\t' << '\\t'\n",
" << std::numeric_limits<int>::min() << '\\t'\n",
" << std::numeric_limits<int>::max() << '\\n' ;\n",
" std::cout << \"float\\t\"\n",
" << sizeof(float) << '\\t' << '\\t'\n",
" << std::numeric_limits<float>::min() << '\\t'\n",
" << std::numeric_limits<float>::max() << '\\n' ;\n",
" std::cout << \"double\\t\"\n",
" << sizeof(double) << '\\t' << '\\t'\n",
" << std::numeric_limits<double>::min() << '\\t'\n",
" << std::numeric_limits<double>::max() << '\\n' ;\n",
" }"
"#include <limits>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"std::cout << \"type\\tsizeof()\\tmin()\\t\\tmax()\\n\" ;\n",
"std::cout << \"uchar\\t\"\n",
" << sizeof(unsigned char) << '\\t' << '\\t'\n",
" << +std::numeric_limits<unsigned char>::min() << '\\t' << '\\t'\n",
" << +std::numeric_limits<unsigned char>::max() << '\\n' ;\n",
"std::cout << \"int\\t\"\n",
" << sizeof(int) << '\\t' << '\\t'\n",
" << std::numeric_limits<int>::min() << '\\t'\n",
" << std::numeric_limits<int>::max() << '\\n' ;\n",
"std::cout << \"float\\t\"\n",
" << sizeof(float) << '\\t' << '\\t'\n",
" << std::numeric_limits<float>::min() << '\\t'\n",
" << std::numeric_limits<float>::max() << '\\n' ;\n",
"std::cout << \"double\\t\"\n",
" << sizeof(double) << '\\t' << '\\t'\n",
" << std::numeric_limits<double>::min() << '\\t'\n",
" << std::numeric_limits<double>::max() << '\\n' ;"
]
},
{
......@@ -86,7 +89,7 @@
"source": [
"## Precision variable des opérations\n",
"\n",
"Lorsque des opérations sont effectuées, elles ne le sont pas nécessairement avec la précision des variables d'origines, mais souvent avec une précision supérieure. Dans l'exemple ci-dessous, bien que partant de variables de type `short`, on voit que le calcul a été fait avec au minimum en `int`, sans quoi le résultat serait faux."
"Lorsque des opérations sont effectuées, elles ne le sont pas nécessairement avec la précision des variables d'origines, mais parfois avec une précision supérieure. Par exemple, un calcul à base de `short` sera toujours évalué comme un `int`. Par contre, un calcul à base de `float` sera évalué comme un `float`... à moins qu'une innocente constante de type `double` fasse basculer le calcul en `double`."