window.h casse la librairie standard

Article original : windows.h breaks the standard library (and my will to live) | Belay the C++ (belaycpp.com)
Traductrice : Chloé Lourseyre

En travaillant sur du code pas si vieux que ça, j’ai eu une erreur de compilation plutôt singulière.

Voici le code incriminé :

//...
 
const T_LongType BIG_OFFSET = std::numeric_limits<T_LongType>::max() / 2;
 
//...

Et voici les erreurs générées :

1>MyFile.cpp(42): error C2589: '(' : illegal token on the right side of '::'
1>MyFile.cpp(42): error C2059: syntax error : '::'
1>MyFile.cpp(42): error C2059: syntax error : ')'
1>MyFile.cpp(42): error C2059: syntax error : ')'

Elles étaient accompagnée d’une petite volée de warnings que je ne posterai pas ici.

Il m’a fallut pas mal de temps pour comprendre quel était le problème. Après tout, le type T_LongType était correctement défini (un typedef de long) et je n’avais pas oublié d’inclure <limits>.

Peut-être connaissez vous déjà la cause de cela. Il s’agit de la ligne suivant :

#include <windows.h>

En effet, si on regarde à l’intérieur de ce header, on tombe là-dessus :

#ifndef NOMINMAX

#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))

#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))

#endif  /* NOMINMAX */

Explication

Le fait que windows.h definisse les macros min et max implique que, pendant la phase de préprocesseur, toutes les instances de min et max sont remplacée par le code de la macro.

Concrètement, cela signifie que lorsque le compilateur compile, au lieu de voir cela :

const T_LongType BIG_OFFSET = std::numeric_limits<T_LongType>::max() / 2;

Il voit cela :

const T_LongType BIG_OFFSET = std::numeric_limits::(((a) > (b)) ? (a) : (b))() / 2;

Ce qui ne fait aucun sens, d’où les erreurs de compilation ci-dessus.

Plusieurs raisons de ne pas inclure windows.h

Voici une liste non-exhaustive expliquant pourquoi inclure ce header est une mauvaise pratique :

  • Il casse la librairie standard juste en l’incluant. On devrait toujours pouvoir utiliser la syntaxe de la librairie standard peut importe les fichiers qu’on inclut.
  • Il vous force à définir NOMINMAX au début de chaque header qui inclut windows.h. Si jamais vous oubliez de le faire, alors tous les fichiers qui incluent le vôtre devront la définir ou risquer de rencontrer les même erreur que moi.
  • C’est un header dependant du system d’exploitation, il faut éviter de l’utiliser tant que c’est possible. Si vous l’utilisez alors que vous pourriez vous en dispenser, alors votre code ne sera plus portable, vous risquez de prendre de mauvaises habitude de codage (en vous reposant trop dessus), sans oublier que plus une librairie est spécifique, moins elle est maintenue.

Conclusion

Il existe des manière d’utiliser windows.h en toute sécurité, mais vous devez être absolument robuste et sans faille, ou vous proveoquerez des effets de bord indésirables.

Tant que vous les pouvez, ne l’utilisez pas.

Article original : windows.h breaks the standard library (and my will to live) | Belay the C++ (belaycpp.com)
Traductrice :
Chloé Lourseyre

Laisser un commentaire