7
votes

Style de correspondance de motif en C ++?

J'adore la correspondance de modèle de style Haskell.

J'ai mon code C ++ comme suit: P>

ObjectPtr ptr;
if(ptr.isType<Foo>()) { // isType returns a bool
  Ptr<Foo> p = ptr.convertAs<Foo>(); // convertAs returns a Ptr<Foo>
  ......
}
if(ptr.isType<Bar>()) {
  Ptr<Bar> p = ptr.convertAs<Bar>();
  ......
}


2 commentaires

Je suppose que vous êtes manquant () après istype .


Dans Mach7, votre code examinera comme suit:


6 Réponses :


7
votes

dynamic_cast semblerait faire ce que vous voulez xxx


1 commentaires

Ensuite, faites une distribution dynamique sur le pointeur contenu - par exemple, si vous utilisez STD :: Auto_PTR (), faites-le du résultat de l'appel d'appel ().



7
votes

J'aime la correspondance de modèle de style Haskell.

Ensuite, écrivez votre programme à Haskell.

Qu'est-ce que vous essayez de faire est un commutateur sur un type. C'est une chose commune que les gens font s'ils veulent éviter les fonctions virtuelles. Maintenant, ces derniers sont une pierre angulaire de ce que OO en C ++ est tout à propos. Si vous voulez les éviter, pourquoi vous programmez en C ++?


comme pour la raison pour laquelle cela est froncé sur: Imaginez que vous avez beaucoup de code comme celui-ci xxx

éreinté sur votre code, puis quelqu'un vient et ajoute baz aux types possibles que pTR pourrait représenter. Maintenant, vous recherchez une base de code de gros code, essayant de trouver tous ces endroits où vous avez changé de type et essayez de découvrir lesquels vous devez ajouter Baz à.

Et, comme Murphy l'a fait, juste lorsque vous avez fait, il existe un foz pour être ajouté en tant que type. (Ou, en pensant à nouveau, si Murphy a sa façon de se glisser dans avant vous avez eu une chance trop complète Ajout de Baz .)


6 commentaires

Contrôle de la mémoire de faible niveau des constructeurs C. Constructeurs et destructeurs d'objets sur la pile <- Ceci est incroyable, car il donne des pointeurs intelligents, Raii, ...; Bibliothèque de modèles standard (une de ces fonctions virtuelles utilise-t-elle?). +1 En supposant que la réponse était une question authentique, pas de troll.


Ce n'était certainement pas une véritable question, mais cela n'était pas non plus un troll. C'était une question rhétorique. Être plain: Vous ne devriez pas faire cela en C ++ . C'est ce que les fonctions virtuelles ont été inventées pour; Ils mettent tout le code relatif aux objets du type FOO dans FOO et tout ce qui concerne Baz dans Baz . Ce n'est pas toujours le meilleur que vous puissiez obtenir (témoin, par exemple, la motivation derrière le modèle de visiteur), mais c'est la valeur par défaut que vous devriez commencer par C ++.


Maintenant, ces derniers sont une pierre angulaire de ce que oo en C ++ est tout environ. Alors pourquoi devrions-nous utiliser des métaprogramming de modèle quand il s'agit essentiellement de FP et non de OO, nous devrions tous aller à HASKEL au lieu d'utiliser le STL, booster ou utiliser nos propres modèles ... Rolleyes En outre seulement quelqu'un ignorant de la C ++ ferait une telle question, Comme ce gars (lien vers pdf) totalement désemparé!


@Ttrinidad: tandis que TMP est effectivement fp, ce n'est certainement pas OO. J'ai eu un regard très superficiel sur ce papier. Corrigez-moi si je me trompe, mais rien que je n'y ai vu à un premier coup d'œil annonce le type classique et simple Switch Type Le choix de l'OP, si commun dans C, qui pleure seulement pour le polymorphisme en C ++. Maintenant, j'avais librement admit à connaître à côté de rien sur Haskell et que mon exposition à Lisp était très courte et il y a une décennie il y a une décennie, alors je pourrais être complètement ici, mais je sais que ce que les désirs de l'OP sont fronçés en C ++ pour très bon les raisons. (J'ai une fois hérité de ce code et était chargé de Baz et foz .)


@SBI Mach7 fait le type de commutation (qui n'est qu'une infime partie de ce qui est appelé correspondant à des modèles) et d'autres choses. Ood fournit des alternatives très verbeuses à la correspondance de motif (même le type de commutation). Imaginez créer une nouvelle méthode virtuelle et une implémentation dans chaque sous-classe pour chaque cas , c'est laid et sur le code, une douleur de maintenance et vous devez créer de nombreuses méthodes et même des sous-classes pour accomplir Le même commutateur simple fait. Dans ce cas, en utilisant des méthodes virtuelles, vous ne faites pas partie de la solution. Voir (Zip W / Source): goo.gl/hnokvo


@Ttrinidad: Si vous avez de nombreuses classes et que vous ajoutez fréquemment des algorithmes, les fonctions virtuelles ne sont pas bien adaptées. OOP a inventé le modèle de visiteur là-bas, mais je n'ai aucune difficulté à vous croire que d'autres langues ont d'autres constructions pour cela et qu'ils sont supérieurs dans certains, voire de nombreuses circonstances. J'ai également eu l'impression que Mach7 peut faire beaucoup de choses et que la capacité de basculer les types n'est qu'un sous-produit. Cependant, ce que le PO souhaité ici était un cas simple que vous résoudiez avec un taquage de type enum dans C. Pour cela, le polymorphisme est généralement meilleur dans de nombreux cas (les plus?).



3
votes

Je suppose que votre modèle code> PTR code> a le concept d'un pointeur NULL.

ObjectPtr ptr;
if(Ptr<Foo> p = ptr.convertAs<Foo>()) { // convertAs returns a NULL pointer if the conversion can't be done.
  ......
}
if(Ptr<Bar> p = ptr.convertAs<Bar>()) {
  ......
}


3 commentaires

Ce n'est-ce que cela ne fait que soulever une autre question - "Comment écrire des convertis () pour faire cela?"


@Neil: Pas vraiment - son code d'origine a supposé l'existence d'une convertis. Cela utiliserait probablement un dynamic_cast, qui produit un pointeur NULL s'il ne peut pas convertir un pointeur sur le type cible. En tant que telle, il est probable que cela soit déjà présent ou assez facile à mettre en œuvre s'il n'est pas présent.


La meilleure partie est, en C ++ 0x, vous pouvez remplacer PTR avec auto .



2
votes

A Pensez que cette macro fait précisément ce que vous voulez: xxx

usage: xxx

Je ne recommanderais pas ce genre de choses Dans le code qui est destiné à être lu par quelqu'un d'autre, mais depuis que vous avez mentionné le mot "macro" ...

aussi, je ne voudrais pas faire quoi que ce soit à faire avec le motif correspondant à Haskell / Style ocaml. Vérifiez Scala si vous voulez une langue qui a une sémantique similaire à C ++ (puits, en quelque sorte) et une correspondance de motif véritable.


0 commentaires

5
votes

Tentative de simuler un style de correspondance de motif en C ++ à l'aide de RTTI est une idée soignée, mais elle est liée à des lacunes, car il existe des différences significatives entre les constructeurs de types de style HASKELL et Standard ML et les sous-classes C ++. (Remarque: ci-dessous, j'utilise Standard ML Syntaxe parce que je suis plus à l'aise avec elle.)

  • dans HASKELLL et ML standard, la correspondance des motifs peut lier les valeurs imbriquées aux variables de motif pour vous (par exemple, le motif A :: B :: C :: DS lie les trois premiers éléments de la liste à A , B et C et le reste de la liste sur DS ). En C ++, vous devrez toujours creuser dans les structures imbriquées réelles, à moins que vous ou quelqu'un d'autre ne propose de macros beaucoup plus compliquées que ce qui a été proposé ici.
  • in Haskell et standard ml, une déclaration de type de données de type constructeur de type DataType 'A option = Aucune | Certains de 'A définissent un nouveau type: ' une option . Constructeurs Aucun et Certains ne sont pas des types, ce sont des valeurs avec des types 'une option et ' a -> 'une option , respectivement. En C ++, lorsque vous définissez des sous-classes telles que FOO et bar pour simuler les constructeurs de types, vous obtenez de nouveaux types.
  • in haskell et ml standard, constructeurs comme Certains sont des fonctions de première classe qui construisent des valeurs du type de données auquel elles appartiennent. Par exemple, Carte Certains ont le type 'une liste ->' une liste d'options . En C ++, en utilisant des sous-classes pour simuler des constructeurs de types, vous n'obtenez pas cette capacité.
  • dans HASKELLL et ML standard, les fichiers de données sont fermés, de sorte que personne ne peut ajouter plus de constructeurs de types sans modifier la déclaration d'origine, et le compilateur peut vérifier au moment de la compilation que le match correspond à tous les cas. En C ++, vous devez vous aider à restreindre qui peut sous-classer votre classe de base.

    À la fin, obtenez-vous suffisamment d'avantages de la correspondance simulée de motif par rapport à l'utilisation de polymorphisme C ++ de manière plus typique? Utilise des macros pour faire un motif simulé correspondant légèrement plus concis (tout en l'obscurci pour tous les autres qui lit votre code) valent la peine?


0 commentaires

4
votes

Nous avons co-écrit une bibliothèque de correspondance de modèle pour C ++ qui vous permet de faire une analyse de motif et de type analyse de manière très efficace. La bibliothèque, appelée Mach7, a été publiée sous licence BSD et est disponible sur GitHub: https://github.com/ SOLODON4 / Mach7 . Vous pouvez trouver des vidéos, des affiches, des diapositives, des papiers ainsi que le code source là-bas. Il prend actuellement en charge GCC 4.4+, Clang 3.4+ et Visual C ++ 2010+. N'hésitez pas à poser des questions à propos de la bibliothèque en soumettant une question GitHub contre son référentiel.


0 commentaires