[Archive — École 42] C++ Modules 07 à 08

Mahaut Latinis
4 min readOct 12, 2023

--

💡Les modules 07 et 08 de C++ de l’école 42 permettent d’appréhender les notions suivantes :

  1. Template de classe, template de fonction
  2. Standard Template Library (containers, iterators, algorithms)

Template de classe, template de fonction

Template

https://cdn.intra.42.fr/video/video/138/piscine_c___-_d07_-_01_templates.mp4

Définir un “template” (patron) (qu’il s’agisse d’une classe ou d’une fonction) nous permet de développer de manière générique et ainsi de définir du code qui fonctionnera indifféremment même si les types de données diffèrent.

Pour cela, les templates que nous définirons porterons des “variables de types” qui seront représentées via le mot clé typename.

Définition d’un template de fonction:

// le mot clé typename signifie qu'il s'agit d'une variable de type
template<typename T>
#include <iostream>

template<typename T>
// T signifie qu'il s'agit d'un type, qui peut etre int ou float ou char etc...
// Préférez prendre des références comme paramètres plutôt que de faire des copies systématiques
// de plus, préférez utiliser des instances const en paramètres et des retours const également
T const &max(T const &x, T const &y)
{
return (X >= Y ? x : y);
}

Une fois défini, il nous faudra instancier notre template.

Pour cela, il est possible de faire une “instantiation explicite” ou une “instantiation implicite”.

int main(void)
{
int a = 21;
int b = 22;

std::cout << max<int>(a,b) << std::endl; // Explicit instanciation
std::cout << max(a,b) << std::endl; // Implicit instanciation

float c = -1.7f;
float d = -4.2f;

std::cout << max<float>(c,d) << std::endl; // Explicit instanciation
std::cout << max(c,d) << std::endl; // Implicit instanciation

}

💡 Par convention, on peut choisir l’extension .tpp pour définir les classes templates.
Définir un template de classe:

#include <iostream>

template<typename T>
class List
{
public:
List<T>(void);
List<T>(T const &content)
{
//...
};
virtual ~List<T>(void);
};
// including the hpp headers

int main(void)
{
List<int> a(42);
List<float> b(42.0f);
return (0);
}

Template avec un type par défaut

https://cdn.intra.42.fr/video/video/137/piscine_c___-_d07_-_03_specialization.mp4

Il est possible de passer des valeurs par défaut à nos variables de types (dans nos templates).

// Déclaration
template<typename T= float>
class Vertex
{
Vertex(void);
virtual ~Vertex(void);

};

// Instantiation
// Ici il ne s'agit pas d'une instantiation implicite
Vertex<> vertex1();

Spécialisation

Lorsque l’on parle de spécialisation, on fait référence au fait de spécifier explicitement un type, plutôt qu’une variable de type. Cela va nous permettre d’implémenter des comportements particuliers pour ce(s) type(s).

La spécialisation peut être partielle ou complète.

https://cdn.intra.42.fr/video/video/137/piscine_c___-_d07_-_03_specialization.mp4

Spécialisation partielle

template<typename T, typename U>
class Pair<T, U>
{
//...
}:

template<typename U>
// Un type est explicité ici
// int est le paramètre "spécialisé"
class Pair<int, U>
{
public:
Pair<int, U>(int lhs, U const &rhs): _lhs(lhs), _rhs(rhs)
{
std::cout << "Int partial specialization" << std::endl;
return ;
}
virtual ~Pair<int, U>(void){};
//...
};

Spécialisation complète

//Spécialisation complète (= plus de typename = plus de variable de type)
template<>
class Pair<bool, bool>
{
//...
};

Standard Template Library (containers, iterators, algorithms)

https://cdn.intra.42.fr/video/video/193/piscine_c___-_d08_-_00_conteneur_et_algorythme.mp4

La Standard Template Library (STL) est une librairie célèbre de C++ qui met à disposition notamment :

  1. des conteneurs (list, map, vector, stack, deque… utilisés pour contenir n’importe quels types des données sous différentes formes -ordonnées ou non-).
  2. des itérateurs (const_iterator, iterator… qui sont une abstraction et permettent de parcourir ces séquences / collections de manière simple et élégante).
  3. des algorithmes (find, forEach… utilisant eux-mêmes les itérateurs, et qui permettent le tri, la recherche, l’insertion ou la suppression -par exemple- au sein de ces collections).

Ces différentes classes sont basées sur les templates et sont particulièrement utiles et optimisées.

Voici quelques exemples (d’instantiation):

// Container list 
std::list<int> lst1;

// iterateur sur list
std::list<int>::const_iterator it;

// Equivalent hash table, dictionnary..
std::map<std::string, int> map1;

// Equivalent tableau
std::vector<int> vect1;
std::vector<int> vect2(42, 100);// 42 entrées qui vont contenir 100

💡 Fun facts sur les itérateurs

  • Un itérateur va pointer sur une valeur, et va permettre de la modifier (à moins que ce soit un const_iterator).
  • Un const_iterator n’est pas un iterator const. S’il est const, il peut modifier la valeur pointée, mais ne peut pas être modifié. S’il s’agit d’un const_iterator: il peut être déplacé (pointeur sur un autre élément de la collection), mais ne peut pas modifier la valeur pointée.
  • On peut définir un const const_iterator, dans ce cas, les deux opérations sont interdites.

Ce sujet étant assez vaste, je vous invite à faire des recherches complémentaires, mais surtout à les utiliser si l’occasion se présente.

Le projet suivant du cursus (supprimé depuis) nommé ft_containers attendait des étudiants qu’ils re codent eux-mêmes certains itérateurs et conteneurs.

Voir article dédié :

https://malatini.medium.com/archive-42-ft-containers-c-containers-stl-library-small-recap-e7eb4c4f2bee

--

--

Mahaut Latinis
Mahaut Latinis

No responses yet