Skip to content

Modernisation de TAcq

GRASLAND Hadrien requested to merge modernization into master

Cette MR profite de la migration C++17 de TAcq pour aligner un peu plus le code TAcq avec les bonnes pratiques actuelles en C++:

Préférer l'utilisation de constexpr à celle du préprocesseur

Contrairement aux #define du préprocesseur...

  • Une valeur constexpr possède un type bien défini et documenté au point de déclaration.
  • Les erreurs dans la définition d'un constexpr ne sont signalées qu'au point de déclaration par le compilateur (et non à chaque point du code où la valeur est utilisée).
  • constexpr est géré au niveau du langage, pas du préprocesseur, ce qui permet des fonctionnalités plus avancées comme effectuer des calculs non triviaux à la compilation.
  • constexpr obéit aux règles normales de scoping du C++ : un constexpr n'est utilisable que dans le scope où il est déclaré, et les variables qu'il utilise sont obtenues depuis ce scope.
  • constexpr obéit aux règles normales d'évaluation d'expressions du C++, pas de copier-coller pouvant avoir des conséquences inattendues en présence d'effets de bord.
  • constexpr a un rôle bien défini (calculer et nommer des constantes de compilation), contrairement aux defines du preprocesseur qui sont utilisés pour tout et n'importe quoi : stocker des valeurs, rendre la compilation configurable, faire des calculs simples selon un formalisme piégeux, définir des types, afficher à la fois le code et la valeur d'une expression en debugging, faire des "fonctions" qui n'apparaissent pas dans les backtraces...
  • Lorsque constexpr est utilisé pour activer/désactiver des fonctionnalités, il est possible de s'assurer que ces fonctionnalités restent compilées, et subissent donc une vérification minimale du compilateur. C'est un avantage par rapport au #ifdef classique qui ne vérifie pas que le code continue de compiler tant que le define n'est pas activé.

L'élimination du préprocesseur dans les endroits où il n'est pas nécessaire a nécessité des changements un peu invasifs dans certaines parties du code, notamment dmamgrv6. Si vous le souhaitez, je peux vous faire un petit tour de ce que j'ai fait spécifiquement dans ce module, et pourquoi je l'ai fait.

Préférer l'utilisation de nullptr à celle de NULL

Le C++ hérite du C la définition de NULL comme #define NULL 0. Cette définition est problématique car elle signifie que NULL peut, dans certains cas, être interprété comme un entier plutôt que comme un pointeur. nullptr n'a pas ce problème (il sera toujours traité comme un pointeur par le compilateur), et c'est donc la constante recommandée pour définir un pointeur nul depuis C++11.

Préférer l'utilisation de la directive #pragma once à celle du trio #ifndef GUARD/#define GUARD/#endif

Même si la directive #pragma once ne fait pas, stricto senso, partie de la norme C++17, elle est supportée par tous les compilateurs C++17 que j'aie jamais utilisés. Son intérêt par rapport aux header guards classique est de réduire la verbosité du code et éviter les erreurs liées au copier-coller du GUARD.

Préférer l'utilisation de noexcept à celle de throw()

La spécification d'exception vide throw() de C++98 souffre d'un défaut de conception qui l'empêche de fournir les bénéfices attendus en termes de qualité du code généré. La directive noexcept de C++11 n'a pas ce problème et répond à quasiment tous les cas d'utilisation de throw(), donc throw() est déprécié en C++17 et supprimé du langage en C++20.

Préférer l'utilisation de using à celle de typedef

La syntaxe de using est cohérente avec celle des expressions C++, donc moins perturbante, et elle a aussi le gros avantage de permettre la définition d'alias de types templatés. using est donc privilégié par rapport à typedef dans tous les nouveaux projets C++.


Globalement, suite à cette migration, j'aurais quelques questions concernant ce qui me semble être des #define dupliqués et qui devraient à mon humble avis être regroupés. Vous trouverez mes commentaires à ce sujet dans le nouveau fichier config.h.

Edited by GRASLAND Hadrien

Merge request reports