Dans ce cas-là la fonction devrait peut-être prendre en entrée un type qui ne peut que représenter les valeurs valides pour la fonction.
Bien sûr ce n'est pas toujours possible (par exemple si la fonction attend une valeur entre 0 et n, avec n variable à l'exécution), mais ici ça semble l'être.
C'est un peu lourd de devoir créer un type pour chaque domaine de valeurs, avec toutes les opérations et conversions qui vont bien.
Et pour les rares cas ou il existe un type de base de domaine correspondant, le manque de vérifications automatiques, la sémantique non-naturelle de ses opérations et la promotion automatique en int me poussent à ne pas l'utiliser.
Je préfère par exemple écrire une classe couleur ainsi :plutôt que comme-ci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 class Color { public: Color(int r, int g, int b) { assert(0 <= r && r <= 255); assert(0 <= g && g <= 255); assert(0 <= b && b <= 255); ... } ... };La vérification du domaine des valeurs a plus sa place à l'intérieur de la fonction qu'à l'extérieur donc avant chaque appel. D'avantage de bugs seront détectés avec la première approche, le code sera plus robuste et plus en accord avec les principes de la programmation par contrat.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 class Color { public: Color(unsigned char r, unsigned char g, unsigned char b) { ... } ... };
Dans le sens que tu présente, je n'en suis absolument pas sur...
En effet, étant donné qu'il s'agit de gérer une valeur potentiellement plus petite que celle donnée, le compilateur se plaindra "tout seul" (comprend sans devoir avoir recours à une assertion) si tu essaye de passer un int là où il attend en réalité un char...
En effet, le passage d'un int là où un char est attendu provoquera au minimum un avertissement sur l'éventuelle perte de données occasionnée par la conversion.
Tu me dira qu'il faut, pour cela, veiller à utiliser les bonnes options de compilation, et décider de porter une attention particulière aux avertissements émis par le compilateur, mais, dans l'ensemble, il s'agit d'une optique que l'on ne peut que promouvoir qui est de compiler en mode "paranoïac", et de veiller à gérer (correctement s'entend ) les avertissements reçus
Il n'en est pas de même, je te l'accorde, si l'on s'attarde à la problématique de la promotion des char (ou short) en int...
Sur le principe, d'accord. Mais il n'y a pas de types entiers contraints en C++, en ajouter est relativement lourd -- il n'y a pas de bon mecanisme pour ajouter des types se comportant comme un type existant, sauf qu'il n'est pas compatible avec (en gros un typedef qui ajouterait un vrai type et pas un alias, mais il faut savoir qu'est-ce qui constitue l'interface -- et qui doit donc toujours etre accessible -- et qu'est-ce qui n'en est pas) sans parler d'ajouter des contraintes. Et c'est tres peu C++; j'ai jamais vu ce qui est l'usage en Ada par exemple, ajouter des types entiers differents pour chaque usage different, meme si les intervalles sont les memes.
Pour commencer, ceux qui utilisent char comme un type entier ont oublie quelque chose: que le fait que char soit signe ou non depend de l'implementation.
Ensuite, il y a les promotions qui font que c1 + c2 est un int meme si c1 et c2 sont des signed char.
(Les choses sont bien comme je l'avais ecrit au debut: plusieurs ecoles et pas d'arguments determinant en faveur d'une ou l'autre.
En fait, je réagissais surtout à l'exemple que Sylvain avait donné avec sa classe "Color"...
Dans son exemple, je trouve "dommage" (risqué ) d'attendre une assertion à l'exécution, qui risque quand même - rappelons le - de "faire planter" le programme quand il sera trop tard (devant le client ) alors qu'il est possible d'avoir la certitude que l'information sera correcte... au moment de la compilation...
Quelque part, je considère toujours que, s'il faut attendre l'exécution pour se rendre compte que l'on a commis une erreur de programmation, c'est que l'on a sans doute... beaucoup trop attendu (pour bien des choses, en tout cas)
En l'absence de types contraints -- j'ai l'impression de radoter -- je ne vois pas d'alternatives. L'utilisation de unsigned char va simplement convertir la valeur recue dans l'intervalle valide, hors c'est le fait que cette conversion soit necessaire qui est l'erreur.
Un langage comme Ada permet pour ce genre de choses au compilateur
- de signaler qu'un probleme arrive a coup sur
- de generer du code qui verifie que le probleme arrive ou non
- de ne pas generer la verification quand il peut prouver que l'erreur n'arrive pas (et le systeme de types permet d'etre dans ces cas la plus souvent qu'avec des passes de propagation d'intervalle, mais ce genre de passe aide aussi).
Pour moi la vérification que la variable est dans le domaine, c'est de la responsabilité de l'appelant et non de l'appelé.La vérification du domaine des valeurs a plus sa place à l'intérieur de la fonction qu'à l'extérieur donc avant chaque appel.
Les asserts détectent justement des cas qui ne devraient pas arriver. Dans un programme idéal, on devrait pouvoir prouver qu'aucun assert n'est jamais appelé.
Les assertions, ce n'est qu'un système de détection de bug.
C'est comme pour la fonction division, (x, 0) ne fait pas partie du domaine. À l'appelant de faire en sorte de ne pas l'appeler avec 0.
Une assertion est utile, mais elle est plus là pour limiter les dégâts et dire "t'as pas fait ce qu'il fallait".
La programmation par contrat dit justement qu'il doit y avoir certaines préconditions vérifiées sur l'entrée.D'avantage de bugs seront détectés avec la première approche, le code sera plus robuste et plus en accord avec les principes de la programmation par contrat.
À toi de faire en sorte que ton entrée valide ces préconditions avant de la fournir à la fonction, donc. Ça ne veut pas forcément dire une vérification, ça peut être déduit de tes invariants...
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager