C++ doit-il moderniser son mécanisme d'inclusion ?
Il y a 3 ans, les développeurs C++ avaient accueilli la nouvelle standardisation du langage avec beaucoup d'enthousiasme. Avec ce nouveau standard, plusieurs fonctionnalités avaient été ajoutées ou mises à jour pour faire du C++ un langage plus moderne et efficace, tout en conservant les anciens avantages tels que l'accès bas niveau à la mémoire par exemple.
Cependant, d'autres améliorations ont été reportées, car il aura fallu quand même 13 ans pour finir cette normalisation!
Une des améliorations possibles, qui restent toujours intéressantes, c'est de repenser le système d'inclusion de fichiers. C'est en tout cas ce que propose l’équipe CoderGears dans un billet de blog. Ils sont même allés plus loin en proclamant que « le C++ doit moderniser son mécanisme d’inclusion pour devenir vraiment un langage moderne ».
Jusqu'à présent, lorsqu'un fichier d'entête est inclus grâce à la directive #include, le préprocesseur analyse le contenu du fichier ainsi que tous les autres fichiers qu'il inclut lui-même. Et ceci est répété à chaque #include rencontré. Ce qui conduit parfois à un grand volume de travail redondant lorsque deux fichiers incluent la même bibliothèque, et que celle-ci n’est pas entourée de #ifndef et #endif. Mais ce n'est pas le seul problème, car lors de l’analyse, si une macro par exemple porte le même nom qu'un autre composant dans cette bibliothèque, c'est toute la compilation qui échoue. « Des problèmes se produisent dans des projets réels lorsque les entêtes pour deux bibliothèques différentes interagissent en raison de collisions macro, et les utilisateurs sont obligés de réorganiser les directives #include ou introduire des #undef pour briser le lien », explique CoderGears.
Certains programmeurs, avec le temps, ont développé de nouvelles habitudes pour éviter ça. Dans la documentation de Clang, on peut lire que « les programmeurs C++ ont adopté un certain nombre de conventions pour travailler autour de la fragilité du modèle de préprocesseur […] Les noms de macros sont écrits avec de LONG_PREFIXES_EN_MAJUSCULES pour éviter les collisions, et certains développeurs de bibliothèques utilisent même un double tiret dans les en-têtes pour éviter les collisions avec des noms "normaux"». Cette pratique, qui ne respecte pas les conventions du langage, est apparemment utilisée par certains pour contourner le problème.
Heureusement, une solution existe depuis la proposition de la norme C++ox, mais elle n'a pas été implémentée et a été retardée pour la norme C++11, puis renvoyée une nouvelle fois à une prochaine standardisation du langage de programmation.
Cette solution devrait alléger grandement le code des entêtes ainsi que leur traitement, puisqu'elle propose de ne plus inclure les fichiers d'une bibliothèque séparément. Par exemple : au lieu de charger les fichiers de la bibliothèque standard du C++ un à un, un simple import std suffira. L'entête gagnera donc beaucoup en clarté. De plus, cela inclura directement le fichier binaire de la bibliothèque (en tant que module déjà prêt), ce qui évitera au préprocesseur de le réanalyser à chaque fois, et évitera en même temps de tomber sur des conflits lors de la compilation.
« L’introduction de modules en C ++ ne sera pas une tâche facile », avoue l’équipe CoderGears. « Nous espérons que ce ne sera pas comme jisgaw (le système modulaire de Java) qui a été reportée de nombreuses années ».
Source : developpez.com
Cependant, d'autres améliorations ont été reportées, car il aura fallu quand même 13 ans pour finir cette normalisation!
Une des améliorations possibles, qui restent toujours intéressantes, c'est de repenser le système d'inclusion de fichiers. C'est en tout cas ce que propose l’équipe CoderGears dans un billet de blog. Ils sont même allés plus loin en proclamant que « le C++ doit moderniser son mécanisme d’inclusion pour devenir vraiment un langage moderne ».
Jusqu'à présent, lorsqu'un fichier d'entête est inclus grâce à la directive #include, le préprocesseur analyse le contenu du fichier ainsi que tous les autres fichiers qu'il inclut lui-même. Et ceci est répété à chaque #include rencontré. Ce qui conduit parfois à un grand volume de travail redondant lorsque deux fichiers incluent la même bibliothèque, et que celle-ci n’est pas entourée de #ifndef et #endif. Mais ce n'est pas le seul problème, car lors de l’analyse, si une macro par exemple porte le même nom qu'un autre composant dans cette bibliothèque, c'est toute la compilation qui échoue. « Des problèmes se produisent dans des projets réels lorsque les entêtes pour deux bibliothèques différentes interagissent en raison de collisions macro, et les utilisateurs sont obligés de réorganiser les directives #include ou introduire des #undef pour briser le lien », explique CoderGears.
Certains programmeurs, avec le temps, ont développé de nouvelles habitudes pour éviter ça. Dans la documentation de Clang, on peut lire que « les programmeurs C++ ont adopté un certain nombre de conventions pour travailler autour de la fragilité du modèle de préprocesseur […] Les noms de macros sont écrits avec de LONG_PREFIXES_EN_MAJUSCULES pour éviter les collisions, et certains développeurs de bibliothèques utilisent même un double tiret dans les en-têtes pour éviter les collisions avec des noms "normaux"». Cette pratique, qui ne respecte pas les conventions du langage, est apparemment utilisée par certains pour contourner le problème.
Heureusement, une solution existe depuis la proposition de la norme C++ox, mais elle n'a pas été implémentée et a été retardée pour la norme C++11, puis renvoyée une nouvelle fois à une prochaine standardisation du langage de programmation.
Cette solution devrait alléger grandement le code des entêtes ainsi que leur traitement, puisqu'elle propose de ne plus inclure les fichiers d'une bibliothèque séparément. Par exemple : au lieu de charger les fichiers de la bibliothèque standard du C++ un à un, un simple import std suffira. L'entête gagnera donc beaucoup en clarté. De plus, cela inclura directement le fichier binaire de la bibliothèque (en tant que module déjà prêt), ce qui évitera au préprocesseur de le réanalyser à chaque fois, et évitera en même temps de tomber sur des conflits lors de la compilation.
« L’introduction de modules en C ++ ne sera pas une tâche facile », avoue l’équipe CoderGears. « Nous espérons que ce ne sera pas comme jisgaw (le système modulaire de Java) qui a été reportée de nombreuses années ».
Source : developpez.com