Nettoyage des inclusions C/C++ dans Visual Studio

À compter de Visual Studio 17.8 Preview 1, Visual Studio fournit une fonctionnalité de nettoyage des #include qui améliore la qualité de votre code de la manière suivante :

Visual Studio fournit une #include fonctionnalité de nettoyage qui améliore la qualité de votre code de la manière suivante :

  • Propose d’ajouter des fichiers d’en-tête pour le code qui ne se compile que parce qu’un fichier d’en-tête nécessaire est inclus indirectement par un autre fichier d’en-tête.
  • Propose de supprimer les fichiers d’en-tête inutilisés, ce qui améliore les temps de génération et la propreté du code.

L’option « Inclure le nettoyage » est désactivée par défaut. Pour savoir comment le configurer, consultez Configurer Include Cleanup pour C/C++ dans Visual Studio.

En-têtes directs et indirects

Certaines terminologies :

  • Un en-tête direct est un en-tête que vous avez explicitement #include dans votre code.
  • Un en-tête indirect est inclus, car un en-tête que vous incluez directement, l’inclut. Vous pouvez également dire qu’un en-tête indirect est inclus transitively.

Include Cleanup analyse votre code et détermine quels en-têtes ne sont pas utilisés et lesquels sont indirectement inclus. Considérez le fichier d’en-tête suivant :

// myHeader.h

#include <string>
#include <iostream>

void myFunc()
{
    std::string s = "myFunc()\n";
    std::cout << s;
}

Et le programme qui l’utilise :

// myProgram.cpp
#include "myHeader.h"

int main()
{
    std::string s = "main()"; // string is indirectly included by myHeader.h
    std::cout << s; // cout is indirectly included by myHeader.h
    myFunc();
}

myHeader.h est un en-tête direct, car myProgram.cpp l’inclut explicitement. myHeader.h inclut <string> et <iostream>, de sorte qu’il s’agit d’en-têtes indirects.

Le problème est que myProgram.cpp utilise std::string et std::cout, mais n’inclut pas directement les en-têtes qui les définissent. Ce code se compile, car myHeader.h inclut ces en-têtes. Ce code est fragile, car si myHeader.h arrêtait d’inclure l’un ou l’autre, myProgram.cpp ne compilerait plus.

Conformément aux instructions C++, il est préférable d’inclure explicitement des en-têtes pour toutes vos dépendances afin que votre code ne soit pas soumis à une fragilité causée par les modifications apportées aux fichiers d’en-tête. Pour plus d’informations sur la recommandation, voir SF.10 : Évitez de dépendre de noms #includeimplicitement qualifiés dans les C++ Core Guidelines.

Include Cleanup analyse votre code pour identifier les en-têtes inutilisés et indirectement inclus. Il fournit des commentaires basés sur les paramètres décrits dans Configurer l’outil #include C++ dans Visual Studio. Les commentaires sont sous la forme d’avertissements et de suggestions de liste d’erreurs. Pour plus d’informations sur les retours fournis par Include Cleanup, consultez les messages d’Include Cleanup.

En-têtes inutilisés

À mesure que votre code évolue, vous n’avez peut-être plus besoin de certains fichiers d’en-tête. Il est difficile de suivre ces en-têtes dans un projet complexe. Au fil du temps, vos builds peuvent prendre plus de temps, car le compilateur traite les fichiers d’en-tête inutiles. Include Cleanup vous permet de rechercher et de supprimer des en-têtes inutilisés. Par exemple, que se passe-t-il si vous mettez myFunc() en commentaire dans myProgram.cpp :

// myProgram.cpp
#include "myHeader.h"

int main()
{
    std::string s = "main()"; // string is indirectly included from myHeader.h
    std::cout << s; // cout is indirectly included from myHeader.h
    // myFunc(); // directly included from myHeader.h
}

Dans la capture d’écran suivante, #include "myHeader.h" est grisé (un paramètre décrit dans Configurer l’outil C++ #include dans Visual Studio), car il n’est plus nécessaire puisque myFunc() est mis en commentaire.

Placez le curseur sur le #include grisé pour afficher le menu d’action rapide. Sélectionnez l’ampoule (ou choisissez le lien Afficher les correctifs potentiels ) pour afficher les actions liées au fichier inutilisé :

Trois options de refactorisation sont affichées : Supprimer # include myHeader.h, supprimer tous les éléments non utilisés, et Ajouter toutes les options transitivement utilisées et supprimer tous les # inutilisés.

Ajouter des en-têtes utilisés de manière transitive

Vous pouvez choisir de supprimer le fichier d’en-tête inutilisé, mais cette action interrompt le code depuis <string> et <iostream> sont indirectement incluses par myheader.h.

Au lieu de cela, nous pouvons choisir Ajouter tous les #includes utilisés transitivement et supprimer tous les #includes inutilisés. Cela supprime l’en-tête myHeader.h inutilisé, mais ajoute également tous les en-têtes utilisés indirectement inclus via myHeader.h. Le résultat, dans ce cas, est l’ajout de #include <string> et #include <iostream> à myProgram.cpp, et la suppression de #include "myHeader.h" :

// myProgram.cpp
#include <iostream>
#include <string>

int main()
{
    std::string s = "main()"; // string is directly included from <string>
    std::cout << s; // cout is directly included from <string>
    // MyFunc();
}

L’outil ne met pas à jour les commentaires, mais vous pouvez voir que le code utilise maintenant std::string et std::cout directement. Ce code n’est plus fragile, car il ne dépend pas de myHeader.h pour inclure les autres en-têtes requis.

Bonnes pratiques

Ne supprimez pas ce qui semble être des fichiers d’en-tête inutilisés sans ajouter d’abord des fichiers d’en-tête inclus indirectement. Votre code peut s’appuyer sur des éléments indirects dans un fichier d’en-tête qui n’est pas utilisé. Ajoutez d’abord les en-têtes utilisés de manière transitive. Ensuite, lorsque vous supprimez des en-têtes inutilisés, vous n’obtenez pas d’erreurs de compilation en raison de fichiers d’en-tête manquants inclus indirectement par un fichier d’en-tête que vous avez supprimé.

Une façon de procéder est la suivante :

  • Définissez le paramètre Nettoyage des inclusions pour Niveau de suggestion pour Ajouter les inclusions manquantes sur Suggestion (Outils>Options>Éditeur de texte>C/C++>Nettoyage du code).
  • Définissez Niveau de suggestion pour la suppression des inclusions inutilisées sur Suggestion.

Une façon de procéder est la suivante :

  • Définissez la liste déroulante du paramètre Include Cleanup pour Choisir comment mettre en surbrillance les directives #include manquantes qui sont incluses transitivement sur Suggestion (Outils>Options>Tous les paramètres>Langages>C/C++>Nettoyage du code>Nettoyage des inclusions).
  • Définissez Choisir comment mettre en surbrillance les directives #include inutilisées sur Suggestion.

Ensuite :

  1. Dans la liste d’erreurs, vérifiez que le filtre est défini sur Build + IntelliSense.
  2. Recherchez les instances de « Contenu de #include x est utilisé dans ce fichier et inclus transitivement ».
  3. Placez votre curseur sur une ligne avec la suggestion. Dans la liste déroulante de l’ampoule, sélectionnez Ajouter tous les includes utilisés transitivement.
  4. Répétez ces étapes dans votre projet jusqu’à ce que toutes les suggestions concernant les includes transitifs soient traitées.
  5. Supprimez les includes inutilisés : dans la liste d’erreurs, recherchez une instance de « #include x n’est pas utilisé dans ce fichier ».
  6. Placez le curseur sur l’en-tête inutilisé. Dans la liste déroulante de l’ampoule, sélectionnez Supprimer tous les includes inutilisés.
  7. Répétez ces étapes dans votre projet jusqu’à ce que toutes les suggestions de Include Cleanup soient traitées.

Dans cette brève vue d’ensemble, vous avez vu comment Include Cleanup peut vous aider à supprimer les en-têtes inutilisés et à ajouter des en-têtes qui ont été indirectement inclus. Ce processus vous aide à nettoyer votre code, à générer potentiellement plus rapidement et à réduire la fragilité de votre code.

Voir aussi

Configurer Include Cleanup pour C/C++ dans Visual Studio
Inclure les messages de nettoyage