Sont les Modèles C++ seulement les Macros dans le déguisement?
J'ai été à la programmation en C++ depuis quelques années, et j'ai utilisé de la STL tout à fait un peu et d'avoir créé mon propre template de cours quelques fois pour voir comment c'est fait.
Maintenant je suis en train d'intégrer des modèles plus profondément dans mon OO design, et une pensée lancinante revient à moi: Ils sont juste un des macros, vraiment... Vous avez pu mettre en œuvre (assez MOCHE) auto_ptrs à l'aide de #définit, si vous avez vraiment voulu.
Cette façon de penser sur les modèles m'aide à comprendre comment mon code fonctionne, mais j'ai l'impression que je dois être à côté de l'essentiel en quelque sorte. Les Macros sont destinés mal incarné, mais "modèle de la métaprogrammation" est à la mode.
Alors, quelles SONT les distinctions? et comment peut-modèles d'éviter les dangers que les #define vous mène dans, comme
- Insondable des erreurs de compilation dans
des endroits où on ne les attend pas? - Code de ballonnements?
- Difficulté dans la recherche de code?
- Réglage Débogueur Points D'Arrêt?
- Pourquoi croyez-vous que le "modèle de la métaprogrammation est à la mode"?
- Non, ils ne sont pas. 🙂 Et votre question est très chargé, car les modèles d'aide avec aucun des problèmes que vous mentionnez. Au lieu de cela ils aider avec une toute autre classe de problèmes vous avez idéalement de l'ignorer. La question présuppose la réponse, et si j'avais le pouvoir, je serais de l'esprit de les disqualifier pour être subjective et argumentitive.
- était-ce un commentaire sur cette question, ou de celui qui s'est fusionné avec le mien? Cette agitation plus d'un an-mortes question est en train de faire ma tête...
- Modèle de la métaprogrammation est fantastique (à la mode) -- au moins je vois une zone portable de la programmation de bas niveau. Les gens ont été en utilisant le préprocesseur(niveau 1) de la méta-programmation depuis le jeton de concaténation en ANSI-C, les possibilités sont infinies avec le C++de mécanisme de template -- c'est à la mode; cependant, nous sommes à court de moyens, et qui met un bémol sur les choses.
Vous devez vous connecter pour publier un commentaire.
Les Macros sont un texte mécanisme de substitution.
Modèles sont une fonctionnelle de turing-complet de la langue qui est exécuté au moment de la compilation, et est intégré dans le C++ type de système. Vous pouvez y penser comme à un plugin mécanisme de la langue.
Ils sont analysés par le compilateur et non pas par un préprocesseur qui s'exécute avant le compilateur.
Voici ce que MSDN dit à ce sujet:
http://msdn.microsoft.com/en-us/library/aa903548(SV.71).aspx
Si ce n'est pas assez pour vous, je ne sais pas ce que c'est.
min
, std::type_identity.template <typename T> T& min(T&, std::type_identity_t<T&>)
Il y a beaucoup de commentaires ici, en essayant de différencier les macros et les modèles.
Oui, ils sont tous les deux la même chose: outils de génération de Code.
Macros sont une forme primitive, sans beaucoup de compilateur application de la loi (comme faire des Objets en C - il peut être fait, mais c'est pas joli). Les modèles sont plus avancés, et ont beaucoup mieux compilateur vérification de type, les messages d'erreur, etc.
Cependant, chacune a des points forts que les autres ne le sont pas.
Modèles ne peut que générer des dynamiques types de classe - les macros peuvent générer presque tous les code que vous voulez (autre que la définition de macro). Les Macros peuvent être très utiles pour intégrer des tableaux statiques de données structurées dans votre code.
Modèles sur l'autre main peut accomplir certains vraiment FUNKY choses qui ne sont pas possible avec des macros. Par exemple:
Le modèle permet au compilateur de créer de façon dynamique et l'utilisation de type sécurisé des instances du modèle à la volée. Le compilateur fait en fait le modèle de paramètre de mathématiques au moment de la compilation, de la création de classes séparées pour chaque résultat unique. Il y a un implicite de l'Unité de<1,-1> (distance /temps = vitesse) de type qui est créé et par rapport à l'intérieur de la conditionnelle, mais jamais explicitement déclaré dans le code.
Apparemment, quelqu'un à une université a défini un modèle de ce genre avec plus de 40 paramètres (besoin d'une référence), chacun représentant un physique type d'unité. Pensez à la sécurité de ce genre de classe, juste pour vos numéros.
#define log(...) someLoggingFunction(__LINE__, __VA_ARGS__)
La réponse est tellement longue que je ne peux pas résumer tout mais:
int
oufloat
définiroperator +
add<float>(5, 3);
pourrait être mis en œuvre différemment queadd<int>(5, 3);
ce qui n'est pas possible avec des macros#define min(i, j) (((i) < (j)) ? (i) : (j))
- lei
etj
paramètres sont évalués à deux reprises. Par exemple, si l'un des paramètres a une postincremented variable, l'incrément est effectué deux foisRemarque: Dans certains cas rares, j'ai préféré en s'appuyant sur les variadic macros, car il n'y a pas une telle chose comme variadic templates jusqu'à ce que le c++0x devient mainstream.C++11 est vivre.Références:
Sur un niveau très basique, oui, du modèle sont juste macro remplacements. Mais vous êtes sauter sur l' beaucoup de choses en pensant à elle de cette façon.
Envisager modèle de spécialisation, ce qui, à ma connaissance, vous ne pouvez pas simuler avec macro. Non seulement le fait de permettre, ainsi, spécial de la mise en œuvre de certains types, il est l'un des éléments clés dans le modèle de méta-programmation:
Ce qui en soi n'est qu'un exemple de la beaucoup de choses que vous pouvez faire. Les modèles eux-mêmes sont Turing-complet.
Il ignore les choses très basiques, tels que la portée, type de sécurité, et que les macro sont messier.
PAS. Un simple contre-exemple: les modèles de respecter les espaces de noms, macro ignorer les espaces de noms (comme ils le sont de préprocesseur consolidés).
Modèles C++ sont un peu comme Lisp les macros (non C macros) dans lesquelles ils opèrent déjà analysé version du code, et qu'ils vous permettent de générer du code arbitraire au moment de la compilation. Malheureusement, la programmation dans quelque chose ressemblant à la crue Lambda calcul, de sorte que des techniques comme le bouclage sont un peu lourdes. Pour tous les détails sanglants, voir Générative de Programmation par Krysztof Czarnecki et Ulrich Eisenecker.
Dans le cas où vous êtes à la recherche pour un traitement plus approfondi de la question, je peux vous tourner vers tous les favori C++ hater. Cet homme sait déteste le plus, C++ que je peux rêver à. Ce simultanément en fait la FQA incroyablement inflammatoire et une excellente ressource.
Ce sont vraiment un gros problème et éviter une multitude de bugs.
Quelque chose qui n'a pas été mentionné, c'est que les modèles de fonctions peuvent déduire les types de paramètre.
L'on peut arguer que le prochain "typeof" opérateur peut fixer cela, mais même il ne peut pas le séparer des autres modèles:
ou encore:
J'ai aussi l'impression que le sujet de la spécialisation n'était pas assez couvert. Voici un exemple simple de ce que les macros ne peuvent pas faire:
L'espace est trop petit pour aller vers le type de spécialisation, mais ce que vous pouvez faire avec elle, autant que je suis concerné, c'est hallucinant.
Non, il n'est pas possible. Le préprocesseur est (à peine) suffisante pour quelques choses comme des conteneurs de T, mais c'est tout simplement insuffisant pour quelques choses d'autres modèles peuvent faire.
Pour des exemples concrets, de lire à travers Moderne de la Programmation en C++, par André Alexandrescu, ou C++ Métaprogrammation par Dave Abrahams et Aleksey Gurtovoy. À peu près rien faire dans les deux livres peuvent être simulées pour plus de extrêmement degré minimal, avec le préprocesseur.
Edit: autant Que
typename
va, l'exigence est assez simple. Le compilateur ne peut pas toujours déterminer si une personne à charge nom fait référence à un type ou pas. À l'aide detypename
explicitement indique au compilateur qu'il se réfère à un type.typename
indique au compilateur qu'un nom particulier est destiné à se référer à un type, pas une variable/valeur, de sorte que (par exemple), vous pouvez définir d'autres variables de ce type.Cette réponse est destinée à faire la lumière sur le préprocesseur C et comment il peut être utilisé pour la programmation générique
Ils sont, à certains égards, car ils permettent d'une même sémantique. Le préprocesseur C a été utilisé pour activer le générique de structures de données et algorithmes (Voir jeton Concatination). Toutefois, sans tenir compte de toutes les autres fonctionnalités de C++ templates, il rend l'ensemble de la programmation générique jeu un BEAUCOUP plus CLAIRE à lire et à mettre en œuvre.
Si quelqu'un veut le voir hardcore C uniquement de programmation générique en action lire la libevent code source -- cela est également mentionné ici. Une vaste collection de conteneur/algorithmes sont mis en œuvre, et de son fait dans UNIQUE fichier d'en-tête (très lisible). J'admire vraiment cette, C++ code du modèle (que je préfère pour ses autres attributs) est TRÈS détaillé.
Essayons primitive exemple. Envisager
invoquée comme
Bien sûr, la vraie différence est plus profonde, mais qui devrait être suffisant pour rejeter similitudes avec les macros.
Modifier: Et non, vous ne pouvez pas assurer la sécurité de type avec des macros. Comment voulez-vous mettre en œuvre typesafe
min()
pour chaque type de définition de moins de comparaison (c'est à direoperrator<
)?min(a, b)
macro qui n'a pas de double-évaluer un argument, et vous ne serez pas seulement d'établir votre point, mais il m'impressionne grandement. Je ne pense pas que cela peut être fait.typeof
dans GCC), qui en combinaison peut autoriser unmin(a, b)
macro qui n'évalue pas ses arguments à deux reprises. Il peut également être défini ou de mise en œuvre de comportement défini qui permet leur mise en œuvre. Mais il n'y a pas de universelle et portable moyen de faire une telle macro, qui est le point ici.Modèles sont de type sécuritaire. Avec les définit, vous pouvez avoir un code qui compile, mais ne fonctionne toujours pas correctement.
Macros s'étendre avant de compilateur obtient le code. Cela signifie que vous obtenez un message d'erreur pour l'expansion de code, et le débogueur ne voit que la version étendue.
Avec des macros, il ya toujours une chance que certains d'expression est évaluée deux fois. Imaginez passer quelque chose comme ++x comme paramètre.
Modèles peuvent être mis dans des espaces de noms, ou être membres d'une classe. Les Macros sont juste une pré-étape de traitement. Fondamentalement, les modèles sont un premier membre de la classe de la langue qui joue de nice (plus agréable?) avec tout le reste.
Modèles peuvent faire beaucoup plus que de la macro du préprocesseur est capable de faire.
E. g. il y a des spécialisations de modèle: Si ce modèle est instancié avec ce type ou constante, de ne pas utiliser la valeur par défaut de mise en œuvre, mais celui-ci...
... modèles peut appliquer certains paramètres sont du même type, etc...
Voici quelques ressources que Vous pouvez voulez regarder:
À mon avis, les macros sont une mauvaise habitude de C. Bien qu'ils peuvent être utiles pour certains, je ne vois pas un réel besoin pour eux quand il y a des typedefs et des modèles. Les modèles sont le prolongement naturel de la Programmation Orientée Objet. Vous pouvez faire beaucoup plus avec les modèles...
Considérer cette...
Afin de faire la conversion vous pouvez utiliser quelque chose qui s'appelle une conversion d'un constructeur et d'un constructeur de séquence (à la fin) le long de la plutôt complet exemple pour une liste:
Ont un look à la de l'information à partir de cplusplus.com sur les modèles! Vous pouvez utiliser des modèles pour faire ce qu'on appelle des traits qui est utilisé a une sorte de documentation pour les types et les tels. Vous pouvez faire beaucoup plus avec des modèles puis ce qui est possible avec les macros!
Le mot-clé typename est présenté afin de permettre contexte imbriqué définition de type de. Elles sont nécessaires pour le caractère technique qui permet de méta-données pour être ajouté à des types (en particulier les types intégrés comme un pointeur), cela était nécessaire pour écrire la STL. Le mot-clé typename est le même que le mot-clé class.
typename
etclass
mots-clés.Modèles comprendre les types de données. Les Macros ne sont pas.
Cela signifie que vous pouvez faire des choses comme la suivante...
En outre, étant donné que les modèles sont de type sécuritaire, il y a un certain nombre de modèle de techniques de codage qui pourrait être réalisée avec un hypothétique avancée de préprocesseur, mais serait encombrants et sujettes à l'erreur, au mieux (par exemple, modèle de paramètres de modèle, le modèle par défaut, les arguments, les modèles de stratégie tel que discuté dans Modern C++ Design).
Il y a quelques problèmes de base avec les macros.
Tout d'abord, ils ne respectent pas la portée ou le type. Si j'ai
#define max(a, b)...
, alors à chaque fois que j'ai le jetonmax
dans mon programme, pour quelque raison que ce soit, il sera remplacé. Il sera remplacé si c'est un nom de variable ou de l'intérieur, profondément imbriquées étendues. Cela peut entraîner dur-à-trouver des erreurs de compilation. En revanche, les modèles de travail à l'intérieur du C++ type de système. Une fonction de modèle peut avoir son nom réutilisés à l'intérieur d'un champ, et de ne pas essayer de réécrire un nom de variable.Deuxième, les macros ne peuvent pas être modifiées. Le modèle
std::swap
normalement il suffit de déclarer une variable temporaire et ne évident affectations, parce que c'est le moyen le plus évident qui fonctionne normalement. Qu'est ce qu'une macro serait limitée. Que serait extrêmement inefficace pour les grands vecteurs, et donc les vecteurs ont uneswap
que les swaps, les références plutôt que l'ensemble du contenu. (Ce qui s'avère être très important dans les choses de la moyenne programmeur C++ ne devrais pas écrire, mais ne l'utilisez.)Troisième, les macros ne peuvent pas le faire de toute forme de type d'inférence. Vous ne pouvez pas écrire un générique de swaps de macro, en premier lieu, parce qu'il aurait pour déclarer une variable d'un type, et il ne sait pas ce type pourrait être. Les modèles sont de type courant.
Un excellent exemple de la puissance des modèles est ce qui a été à l'origine appelé le Modèle Standard de la Bibliothèque, qui est dans la norme des containers et des algorithmes et des itérateurs. Jetez un oeil à la façon dont ils fonctionnent, et essayez de penser à comment vous pouvez le remplacer avec des macros. Alexander Stepanov regardé sur une grande variété de langues, de mettre en œuvre son STL idées, et conclu que le C++ à l'aide de modèles a été le seul à travailler en.
Modèles ne sont semblables à des macros dans leur la plupart des fonctionnalités de base. Après tout, les modèles ont été introduits dans la langue comme "civilisé" alternative à des macros. Mais même quand il s'agit de ce que la plupart des fonctionnalités de base, la similitude est que la peau en profondeur.
Cependant, une fois que nous obtenons pour les fonctionnalités plus avancées de modèles, comme la spécialisation (partielle ou explicite) apparente similitude avec les macros disparaît entièrement.
Bien que les paramètres du modèle sont de type vérifié et il ya de nombreux avantages de modèles sur les macros, les modèles sont très bien comme les macros en ce qu'ils sont toujours basés sur le texte de substitution. Le compilateur ne va pas vérifier que votre modèle de code ne fait aucun sens, jusqu'à vous donner les paramètres de type de substitut. Visual C++ n'est pas se plaindre de cette fonction aussi longtemps que vous n'avez pas vraiment appeler ça:
Edit: Cet exemple s'applique uniquement à Visual C++. Dans standard C++ votre modèle de code est analysé dans un arbre de syntaxe avant, le modèle est déjà utilisé, afin que l'exemple est acceptée par VC++ mais pas GCC ou Clang. (J'ai appris cela quand j'ai essayé de port VC++ code de GCC et a dû faire face avec des centaines d'erreurs de syntaxe dans mon non spécialisé modèles.) Toutefois, un arbre de syntaxe ne fonctionne toujours pas nécessairement un sens sémantiquement. Quel que soit le compilateur, pas de vérification de type se produit dans le corps jusqu'à ce que vous instancier le modèle en fournissant
<template arguments>
.Par conséquent, il est, en général, impossible de savoir si votre modèle de code fonctionne correctement, ou de compiler avec succès, pour une catégorie donnée du type de paramètres que le modèle est conçu pour accepter.
Garbage<int>
est une fonction, qui ne peut pas compiler.Ce n'est pas une réponse tellement comme une conséquence de l'réponses déjà dit.
De travail avec des scientifiques, des chirurgiens, des artistes graphiques et d'autres qui ont besoin de programme - mais ne le sont pas et ne seront jamais professionnel à plein temps, les développeurs de logiciels - je vois que les macros sont facilement comprises par le programmeur occasionnel, tandis que les modèles semblent exiger un niveau plus élevé de la pensée abstraite possible seulement avec la plus profonde et l'expérience en cours de programmation en C++. Il prend de nombreux cas de travail avec le code où les modèles sont utiles concept, le concept de donner un sens suffisamment pour les utiliser. Tout ce qu'on peut dire de tout le langage, le montant de l'expérience pour les modèles présente un écart plus grand que le spécialiste casual programmeur est susceptible d'obtenir à partir de leur travail de tous les jours.
La moyenne de l'astronome, ingénieur en électronique, probablement groks macros très bien, et peut même comprendre pourquoi les macros doivent être évités, mais ne connaît pas les modèles bien assez pour un usage quotidien. Dans ce contexte, les macros sont en fait mieux. Naturellement, il existe de nombreuses poches des exceptions; certains physiciens exécuter des cercles autour de la pro ingénieurs en logiciel, mais ce n'est pas typique.
Modèles offrent un certain degré de sécurité de type.
Modèles sont intégrés dans la langue et sont de type sécurisé.
Dites-moi comment vous voulez faire cela avec des macros. C'est lourd modèle de la métaprogrammation.
https://www.youtube.com/watch?v=0A9pYr8wevk
Je pense que les macros, autant que je sache, ne peut pas calculer les types de la façon dont ce modèle partielle spécialisations peuvent le faire.