---
jupytext:
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
kernelspec:
  display_name: C++17
  language: C++17
  name: xcpp17
rise:
  auto_select: first
  autolaunch: false
  centered: false
  controls: false
  enable_chalkboard: true
  height: 100%
  margin: 0
  maxScale: 1
  minScale: 1
  scroll: true
  slideNumber: true
  start_slideshow_at: selected
  transition: none
  width: 90%
---

+++ {"slideshow": {"slide_type": "slide"}}

# Digressions : surcharge, templates, espaces de noms, ...

Nous allons maintenant faire quelques digressions, pour pointer vers
des fonctionnalités de C++ que nous avons utilisées sans explications
jusqu'ici, et dont l'usage est naturel et potentiellement utile dès
maintenant.

+++ {"slideshow": {"slide_type": "slide"}, "tags": []}

## Surcharge de fonctions ♣

+++ {"slideshow": {"slide_type": "fragment"}}

### Exemple : la fonction `monMax`

+++ {"slideshow": {"slide_type": "skip"}, "tags": []}

Nous avons vu maintes fois la fonction `max` sur les entiers :

```{code-cell}
---
slideshow:
  slide_type: fragment
tags: []
---
int monMax(int a, int b) {
    if ( a < b )
        return b;
    else
        return a;
}

monMax(1,3)
```

+++ {"slideshow": {"slide_type": "skip"}, "tags": []}

On remarquera que le code est générique : on peut par exemple calculer
de même le maximum de deux nombres réels :

```{code-cell}
---
slideshow:
  slide_type: fragment
tags: []
---
double monMax(double a, double b) {
    if ( a < b)
        return b;
    else
        return a;
}

monMax(1.0, 3.5)
```

+++ {"slideshow": {"slide_type": "skip"}, "tags": []}

ou même de deux chaînes de caractères :

```{code-cell}
---
slideshow:
  slide_type: fragment
tags: []
---
using namespace std;
```

```{code-cell}
:tags: []

string monMax(string a, string b) {
    if ( a < b)
        return b;
    else
        return a;
}

monMax("toto", "alfred")
```

+++ {"slideshow": {"slide_type": "fragment"}}

:::{hint} Observation
Nous avons utilisé chaque fois le même nom de fonction et
`C++` a appelé automatiquement la bonne version.
:::

+++ {"slideshow": {"slide_type": "fragment"}}

:::{hint} Remarque
Il serait de même possible d'utiliser le même nom de fonction pour le
max à trois arguments (et plus!) :
:::

```{code-cell}
:tags: []

int monMax(int a, int b, int c) {
    return monMax(monMax(a, b), c);
}

monMax(2,4,3)
```

+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}

:::{attention} Attention aux ambiguïtés
<br>
:::

```{code-cell}
:tags: []

monMax(3, 4.5)
```

+++ {"slideshow": {"slide_type": "slide"}, "tags": []}

:::{prf:definition} ***Surcharge de fonction***
-   En C++, on peut avoir plusieurs fonctions avec le même nom et des
    signatures différentes
-   Idem en Java, mais pas en C ou en Python par exemple!
:::

+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}

:::{hint} Bonne pratique 
Il est recommandé que toutes les fonctions ayant le même nom aient
la même *sémantique*
:::

+++ {"slideshow": {"slide_type": "slide"}, "tags": []}

## Digression : templates ♣

:::{warning} Problème
L'exemple précédent n'est pas satisfaisant : on a dû implanter la
fonction `monMax` pour chaque type sur lequel on peut faire une
comparaison, en dupliquant le même code.
:::

+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}

:::{hint} Solution
Les ******templates****** pour écrire du code *générique*
:::

+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}

La fonction `monMax` suivante est valide pour tout type sur lequel on
peut faire des comparaisons :

```{code-cell}
---
slideshow:
  slide_type: fragment
---
template<class T>
T monMax(T a,T b) {
    if ( a < b )
        return b;
    else
        return a;
}
```

```{code-cell}
---
slideshow:
  slide_type: fragment
---
monMax(1,3)
```

```{code-cell}
---
slideshow:
  slide_type: fragment
---
monMax(string("toot"), string("alfred"))
```

```{code-cell}
---
slideshow:
  slide_type: fragment
---
monMax(1.4, 0.5)
```

```{code-cell}
---
slideshow:
  slide_type: fragment
---
monMax(8.0, 4)
```

+++ {"slideshow": {"slide_type": "fragment"}}

Les détails seront pour un autre cours!

+++ {"slideshow": {"slide_type": "slide"}}

## Digression : espaces de noms ♣

:::{warning} Problème

Des milliers de développeurs écrivent des bibliothèques, bibliothèques
qui sont par la suite combinées entre elles de multiples façons non
anticipées à l'origine.

Comment s'assurer qu'il n'y a pas de conflit
entre deux fonctions portant le même nom et la même signature dans
deux bibliothèques différentes?
:::

+++ {"slideshow": {"slide_type": "fragment"}}

:::{hint} Solution
Isoler chaque bibliothèque dans un ******espace de noms******
:::

+++ {"slideshow": {"slide_type": "fragment"}}

:::{prf:example}
La bibliothèque standard C++ utilise l'espace de nom `std`. Ainsi,
dans le programme suivant, il faudrait en principe mettre `std`
devant `cout`, et `endl`.
:::

```{code-cell}
---
slideshow:
  slide_type: fragment
---
#include <iostream>
int main() {
    std::cout << "Bonjour!" << std::endl;
    return 0;
}
```

+++ {"slideshow": {"slide_type": "fragment"}}

:::{hint} Explication
Notre incantation magique :
``` c++
using namespace std;
```
dit simplement de définir des raccourcis pour rendre accessible
directement tout ce qui est défini dans l'espace de nom `std`.
:::

+++ {"slideshow": {"slide_type": "fragment"}}

Vous verrez plus tard comment créer vos propres espaces de noms.