web-dev-qa-db-fra.com

Comment dois-je écrire mon C ++ pour être préparé pour les modules C ++?

Il existe déjà deux compilateurs qui prennent en charge les modules C++:

Lors du démarrage d'un nouveau projet maintenant, à quoi dois-je faire attention pour pouvoir adopter la fonctionnalité des modules lorsqu'elle sera finalement publiée dans mon compilateur?

Est-il possible d'utiliser des modules tout en conservant la compatibilité avec les anciens compilateurs qui ne le prennent pas en charge?

54
user7610

Il existe déjà deux compilateurs qui prennent en charge les modules C++

clang: http://clang.llvm.org/docs/Modules.html MS VS 2015: http://blogs.msdn.com/b/vcblog/archive/2015/ 12/03/c-modules-in-vs-2015-update-1.aspx

L'approche de Microsoft semble être celle qui gagne le plus de succès, principalement parce que Microsoft consacre beaucoup plus de ressources à sa mise en œuvre que n'importe quel autre clang. Voir https://llvm.org/bugs/buglist.cgi?list_id=100798&query_format=advanced&component=Modules&product=clang pour ce que je veux dire, il y a de gros bugs showstopper dans les modules pour C++, alors que les modules pour C ou en particulier l'objectif C semble beaucoup plus utilisable dans le code du monde réel. Le client le plus important et le plus important de Visual Studio, Microsoft, pousse dur pour les modules car il résout une tonne de problèmes d'évolutivité de la construction interne, et le code interne de Microsoft est l'un des C++ les plus difficiles à compiler n'importe où dans l'existence, vous ne pouvez donc pas lancer de compilateur autre que MSVC (par exemple, bonne chance pour obtenir clang ou GCC pour compiler les fonctions de ligne 40k). Par conséquent, les astuces de construction de clang utilisées par Google, etc. ne sont pas disponibles pour Microsoft, et ils ont un énorme besoin urgent de le faire réparer le plus tôt possible.

Cela ne veut pas dire qu'il n'y a pas de graves défauts de conception avec la proposition de Microsoft lorsqu'elle est appliquée dans la pratique à de grandes bases de code du monde réel. Cependant, Gaby est d'avis que vous devriez refactoriser votre code pour les modules, et même si je ne suis pas d'accord, je peux voir d'où il vient.

Lors du démarrage d'un nouveau projet maintenant, à quoi dois-je faire attention pour pouvoir adopter la fonctionnalité des modules lorsqu'elle sera finalement publiée dans mon compilateur?

Dans la mesure où le compilateur de Microsoft est actuellement censé implémenter des modules, vous devez vous assurer que votre bibliothèque est utilisable sous toutes ces formes:

  1. Bibliothèque dynamique
  2. Bibliothèque statique
  3. Bibliothèque d'en-tête uniquement

Quelque chose de très surprenant pour beaucoup de gens est que les modules C++, comme on s'attend actuellement à ce qu'ils soient mis en œuvre, conservent ces distinctions, alors maintenant vous obtenez une variante de module C++ pour les trois de ce qui précède, le premier ressemblant le plus à ce que les gens attendent d'un module C++, et le dernier ressemblant le plus à un en-tête précompilé plus utile. La raison pour laquelle vous devez prendre en charge ces variantes est que vous pouvez réutiliser la plupart des mêmes machines de préprocesseur pour prendre également en charge les modules C++ avec très peu de travail supplémentaire.

Une version ultérieure de Visual Studio permettra de lier le fichier de définition de module (le fichier .ifc) en tant que ressource dans les DLL. Cela éliminera enfin le besoin de la distinction .lib et .dll sur MSVC, vous fournissez simplement un seul DLL au compilateur et tout "fonctionne" à l'importation de module, pas d'en-têtes ou quoi que ce soit bien sûr, cela sent un peu comme COM, mais sans la plupart des avantages de COM.

Est-il possible d'utiliser des modules dans une seule base de code tout en conservant la compatibilité avec les anciens compilateurs qui ne le prennent pas en charge?

Je suppose que vous vouliez dire le texte en gras inséré ci-dessus.

La réponse est généralement oui avec encore plus de plaisir pour les macros de préprocesseur. #include <someheader> peut se transformer en import someheader dans l'en-tête car le préprocesseur fonctionne toujours comme d'habitude. Vous pouvez donc baliser des en-têtes de bibliothèque individuels avec la prise en charge des modules C++ sur quelque chose comme ces lignes:

// someheader.hpp

#if MODULES_ENABLED
#  ifndef EXPORTING_MODULE
import someheader;  // Bring in the precompiled module from the database
// Do NOT set NEED_DEFINE so this include exits out doing nothing more
#  else
// We are at the generating the module stage, so mark up the namespace for export
#    define SOMEHEADER_DECL export
#    define NEED_DEFINE
#  endif
#else
// Modules are not turned on, so declare everything inline as per the old way
#  define SOMEHEADER_DECL
#  define NEED_DEFINE
#endif

#ifdef NEED_DEFINE
SOMEHEADER_DECL namespace someheader
{
  // usual classes and decls here
}
#endif

Maintenant dans votre main.cpp ou autre chose, vous faites simplement:

#include "someheader.hpp"

... et si le compilateur avait/experimental: modules/DMODULES_ENABLED, alors votre application utilise automagiquement l'édition des modules C++ de votre bibliothèque. Si ce n'est pas le cas, vous obtenez une inclusion en ligne comme nous l'avons toujours fait.

Je pense que ce sont le minimum possible de modifications de votre code source pour rendre votre code prêt pour les modules maintenant. Vous remarquerez que je n'ai rien dit sur les systèmes de construction, c'est parce que je suis toujours en train de déboguer les outils cmake que j'ai écrits pour que tout cela fonctionne "de manière transparente" et je m'attends à le déboguer pendant quelques mois encore. Attendez-vous à le voir peut-être lors d'une conférence C++ l'année prochaine ou l'année suivante :)

26
Niall Douglas

Est-il possible d'utiliser des modules tout en conservant la compatibilité avec les anciens compilateurs qui ne le prennent pas en charge?

Non ce n'est pas possible. Il pourrait être possible d'utiliser un #ifdef magie comme ceci:

#ifdef CXX17_MODULES
    ...
#else
    #pragma once, #include "..." etc.
#endif

mais cela signifie que vous devez toujours fournir .h support et donc perdre tous les avantages, plus votre code base est maintenant assez laid.

Si vous souhaitez suivre cette approche, la méthode la plus simple pour détecter "CXX17_MODULES "que je viens de créer est de compiler un petit programme de test qui utilise des modules avec un système de build de votre choix, et de définir un global pour que chacun puisse voir si la compilation a réussi ou non.

Lors du démarrage d'un nouveau projet maintenant, à quoi dois-je faire attention pour pouvoir adopter la fonctionnalité des modules lorsqu'elle sera finalement publiée dans mon compilateur?

Ça dépend. Si votre projet est d'entreprise et vous apporte de la nourriture dans l'assiette, j'attendrais quelques années une fois qu'il sera sorti dans les écuries pour qu'il devienne largement adapté. D'un autre côté, si votre projet peut se permettre d'être saignant-Edge, par tous les moyens, utilisez des modules.

Fondamentalement, c'est la même histoire avec Python3 et Python2, ou moins pertinent, PHP7 et PHP5. Vous devez trouver un équilibre entre être un bon programmeur à jour et ne pas ennuyer les gens sur Debian ;-)

3
rr-