Les modèles C ++ ne sont-ils qu'une sorte de macros glorifiées?

27

À partir de différentes comparaisons entre les modèles C ++ et les génériques C # / Java comme celui-ci-

/programming/31693/what-are-the-differences-between-generics-in-c-and-java-and-templates-in-c/31929#31929

J'ai l'impression que les modèles C ++ sont implémentés par une sorte de prétraitement (remplacement de texte brut avant l'analyse), et non par compilation. Parce que la vérification de type dans les modèles C ++ ressemble aux macros C. Je veux dire, s'il y a des erreurs, ce sont des erreurs du code généré après le traitement des blocs de code modèles, pas des modèles eux-mêmes. En d'autres termes, ils ne sont qu'une sorte de version supérieure des macros en C.

Ensuite, j'ai trouvé d'autres faits à l'appui de cela-

  • Je pensais que si les modèles C ++ étaient implémentés par prétraitement, il y aurait des problèmes avec la liaison dynamique (en utilisant .dll). Et une recherche rapide sur Google l'a soutenu.

  • Un autre point est que les constantes entières peuvent être passées comme arguments aux modèles. Et il prend même en charge une sorte de récursivité. Mais cette récursivité n'est pas trouvée dans le code assemblé / machine compilé. La chose récursive est gérée au moment de la compilation en générant une fonction pour chaque appel récursif et en ayant ainsi un binaire exécutable plus grand mais plus rapide.

Bien que contrairement aux macros C, il possède des capacités supérieures. Mais le modèle C ++ n'est-il pas implémenté avec une sorte de prétraitement? Comment est-ce implémenté dans différents compilateurs C ++?

Gulshan
la source
19
Nan. Les modèles C ++ sont compilés.
Edward Strange
2
Quelle est votre définition du "prétraitement"? Et de "compiler"? Une définition suffisamment large du "prétraitement" pourrait inclure tout ce qu'un compilateur fait; après tout, un compilateur traite vraiment la source avant de l'exécuter, non?
James McNellis
@James McNellis À mon humble avis, si vous pouvez simplement différencier le prétraitement de toutes les autres choses faites pour la compilation, il suffit de comprendre ma question. Pour clarifier le préprocesseur
Gulshan
6
Si vous faites référence à cette forme de prétraitement, alors non, les modèles C ++ ne sont absolument pas une sorte de macro glorifiée.
James McNellis
1
Le langage du modèle est en fait très complet, ils sont donc bien plus que des macros améliorées.
davidk01

Réponses:

9

Les modèles C ++ sont une sorte de macros Lisp abrégées (ou même plus, Scheme). C'est un langage Turing-complet qui évalue au moment de la compilation, mais il est sévèrement limité car il n'y a pas d'accès de ce langage à l'environnement C ++ sous-jacent. Donc, oui, les modèles C ++ peuvent être considérés comme une forme de prétraitement, avec une interaction très limitée avec le code généré.

SK-logic
la source
2
"mais il est sévèrement limité car il n'y a pas d'accès de ce langage à l'environnement C ++ sous-jacent." -- Qu'est-ce que ça veut dire? J'ai essayé d'analyser cette déclaration, mais j'ai échoué.
quant_dev
2
Uhm, en fait ... github.com/kmichel/bf0x
Anton Golov
3
@ SK-logic: En aparté, C ++ 11 est C ++, sauf si vous traitez (pédantiquement) différentes versions du même langage comme des langages différents.
Jon Purdy
3
@Jon Purdy, C ++ 11 n'existait pas (officiellement) au moment de cette réponse. De nos jours, un exemple aurait été plus compliqué, comme la décomposition d'une structure de données, l'utilisation d'une fonction de bibliothèque, etc.
SK-logic
1
@ SK-logic: Connaissez-vous justement l'implémentation de C ++ avec des macros de type Lisp? J'en ai marre des limitations des modèles. Un exemple de langage de syntaxe de style C ++ avec un puissant système de macro dans Haxe: haxe.org/manual/macros . (Cela ne m'aide pas parce que j'utilise C ++ à sa fin - la programmation de microcontrôleurs 8 bits; il y a de meilleurs langages pour autre chose).
pfalcon
41

La plus grande différence est probablement que les macros C sont développées dans la phase de prétraitement, avant toute autre compilation, tandis que les modèles C ++ font partie de la compilation. Cela signifie que les modèles C ++ sont sensibles au type et étendus, entre autres, et ne sont pas de simples substitutions textuelles. Ils peuvent se compiler en fonctions réelles et éviter ainsi la plupart des problèmes rencontrés par les macros. Être conscient du type signifie qu'ils peuvent être généraux ou spécialisés: par exemple, il est facile de fournir une swapfonction de modèle et d'écrire des spécialisations qui fonctionnent bien même si les objets gèrent la mémoire de tas.

Par conséquent: les modèles C ++ ne sont pas de prétraitement dans le même sens que les macros, ils ne sont pas une sorte de macro C et il est impossible d'utiliser des macros C pour dupliquer ce que font les modèles.

Les modèles vivent dans des fichiers d'en-tête, pas dans des bibliothèques liées, c'est vrai, mais si vous fournissez un fichier .dll, vous fournissez probablement un fichier d'en-tête à utiliser.

David Thornley
la source
12
Ils n'ont pas besoin de vivre dans le fichier d'en-tête (c'est juste la technique la plus simple pour les utiliser). Vous pouvez les définir dans un fichier source et forcer manuellement l'instanciation du modèle dans le fichier source (unité de compilation). La liaison reprendra alors les instanciations comme d'habitude (c'est une technique pour limiter les modèles à des types spécifiques et ne pas autoriser tous les types génériques).
Martin York
@Martin: Je ne sais pas si cette technique (bien que prise en charge) est réellement explicitement prise en charge par la norme. Sinon, tous les compilateurs auraient exportdéjà été implémentés. Je sais que cela fonctionne pour les fonctions, mais je doute que cela fonctionne pour les classes: comment connaîtrez-vous leur taille?
Matthieu M.
@Matthieu M: Cela n'a rien à voir avec le mot-clé d'exportation. Il traite de l'instanciation de modèle "explicite" et est bien défini dans la norme.
Martin York
2
@Matthieu M .: Si le compilateur connaît la signature d'une fonction et que l'éditeur de liens peut trouver une implémentation, tout va bien. Cela s'applique que la fonction soit ou non une fonction de modèle. En pratique, ils vivent généralement dans des fichiers d'en-tête, car forcer des instanciations spécifiques est généralement plus de travail que cela en vaut la peine, mais Martin a raison de noter l'alternative.
David Thornley
Je sais que cela fonctionne, bien sûr, pour des fonctions spécialisées. Cependant, je suis également tout à fait sûr que cela ne fonctionne pas pour les cours, ce qui était mon point. Je pense que cela fonctionne aussi pour les méthodes des classes spécialisées, mais je ne sais pas si c'est standard.
Matthieu M.
5

Est-il important de savoir comment ils sont mis en œuvre? Les premiers compilateurs C ++ n'étaient que des pré-processeurs qui alimentaient le code en un compilateur alternatif, cela ne signifie pas que C ++ n'est qu'une macro glorifiée.

Les modèles suppriment le besoin de macros en fournissant un moyen plus sûr, plus efficace et spécialisable (même je ne pense pas que ce soit un vrai mot) d'implémenter du code pour plusieurs types.

Il existe une variété de façons de faire du modèle de code de type en c, dont aucune n'est très agréable une fois que vous avez dépassé les types simples.

Martin Beckett
la source
Je n'ai pas dit que C ++ était une macro glorifiée. J'admire beaucoup le C ++. Être juste curieux.
Gulshan
2
@Gulshan: Non, vous n'avez rien dit à ce sujet. Néanmoins, c'est ainsi que les premiers compilateurs C ++ fonctionnaient (sauf que CFront était quelque chose d'un compilateur au lieu d'un simple préprocesseur de macro), et vos déclarations sur les modèles C ++ sont à peu près aussi applicables au début C ++ lui-même.
David Thornley
CFront a compilé C ++ en C. La ligne entre le préprocesseur et le compilateur est clairement définie: un compilateur tente de comprendre son entrée - via l'analyse, la construction AST, etc. - tandis qu'un préprocesseur ne le fait pas - par exemple, en utilisant uniquement la substitution textuelle ou de jeton.
Jon Purdy
1
Je pense que ce que voulait dire David, c'est qu'il existe un sous-ensemble sous-jacent de C ++ et que les modèles peuvent être considérés comme une sorte de macros qui sont utilisées pour généraliser un programme dans ce sous-ensemble, qui peut ensuite être compilé comme une étape distincte supplémentaire.
Giorgio
5

Il y a quelques différences; par exemple, les modèles peuvent être utilisés pour instancier une surcharge de fonction en cas de besoin, tandis qu'avec les macros, vous devrez développer la macro une fois pour chaque surcharge possible afin de la rendre visible au compilateur, vous vous retrouverez donc avec beaucoup de code inutilisé.

Une autre différence est que les modèles respectent les espaces de noms.

Simon Richter
la source
2

À mon humble avis, les modèles C ++ et les macros C étaient censés résoudre deux problèmes entièrement différents. La bibliothèque de modèles standard C ++ d'origine était un mécanisme permettant de découpler proprement les classes de conteneurs (tableaux, listes chaînées, etc.) des fonctions génériques qui leur sont généralement appliquées (comme le tri et la concaténation). Avoir des représentations abstraites d'algorithmes efficaces et de structures de données conduit à un code plus expressif car il y avait beaucoup moins de conjectures sur la meilleure façon d'implémenter une fonction travaillant sur une donnée particulière. Les macros C étaient beaucoup plus conformes à ce que l'on verrait généralement dans les macros Lisp, en ce sens qu'elles fournissaient un moyen d'étendre le langage avec du code intégré. Ce qui est cool, c'est que la bibliothèque standard C ++ a étendu les fonctionnalités des modèles pour couvrir la grande majorité de ce que nous utilisons #définir en C.

Marc
la source