Je pense que le problème est assez courant. Vous avez une chaîne d'entrée et devez appeler une fonction en fonction du contenu de la chaîne. Quelque chose comme un commutateur () pour les chaînes. Pensez aux options de ligne de commande.
J'utilise actuellement: p> et dans l'en-tête p> donc chaque Foo et Bar, je dois répéter quatre (4!) fois. Je sais que je peux nourrir les pointeurs de fonction et les chaînes à une matrice statique avant et effectuer la répartition dans une boucle, en sauvegarde de certaines ... des lignes d'autre. Mais existe-t-il une certaine macro tromperie (ou un abus de préprocesseur, en fonction du POV), ce qui permet d'en quelque sorte définir une manière d'une manière ou d'une autre, de définir la fonction et de mettre en même temps la mise à jour de la matrice automatiquement?
Donc, je devrais l'écrire que deux fois, ou éventuellement une fois si utilisé en ligne? P> Je recherche une solution en C ou C ++. P> P>
5 Réponses :
On dirait que vous recherchez le modèle de commande
quelque chose comme ceci: p>
Créer une carte comme celle-ci p> Il suffit d'utiliser votre clé pour exécuter la commande comme celle-ci .... p> myMap["foo"] = new CommandFoo("someArgument");
myMap["bar"] = new CommandBar("anotherArgument");
Non, il est probablement trompeur que j'ai utilisé des fonctions appelées "cmd_ *", mais ils pourraient être quelque chose de différent, il n'est pas nécessaire de ne pas représenter des commandes. Le répartiteur supplémentaire n'a pas besoin d'être lié dans un objet.
@drhirsch. Ils ne doivent pas nécessairement être des commandes réelles. C'est juste le nom du modèle. Fondamentalement, c'est un moyen d'exécuter un code prédéfini basé sur une entrée
Je pense que la solution Neil et Glen suggèrent la bonne réponse. Cela n'inclut pas l'auto-enregistrement, mais je ne suis pas sûr qu'il y ait un moyen propre de le faire en C ++. En Java ou C #, ce serait très faisable, cependant.
@Steven Vous pourriez probablement faire l'auto-inscription en utilisant une forme d'initialisation statique dans chacune des classes de commande. Bien que vous auriez probablement besoin de faire votre STD :: Carte d'un singleton. Comme tu dis que ce n'est pas très propre
Il n'a pas besoin d'être propre, notez que j'ai explicitement askd pour les abus de préprocesseur. Mais cette solution semble très intéressante, cela me donne quelques nouvelles idées. Mais maintenant, j'ai besoin des déclarations et des constructeurs de commandes de commande et de commande de la barre de commande, alors je répète FOO et Bar quatre fois à nouveau.
Eh bien, coupez le constructeur, alors je suis jusqu'à trois. +1 pour l'amélioration.
@Glen: À droite, mais alors vous auriez des problèmes potentiels impliquant l'ordre de l'initialisation des membres statiques parmi les modules. Cela peut devenir un peu laid.
comme alternative au modèle de commande vous Peut construire une haquetable forte> de forte> de String fort> -> pointeurs de fonction strong>:
Ce n'est pas une alternative réelle au modèle i>: c'est le même concept, mis en œuvre différemment.
La solution macro laide, que vous avez aimé. Notez qu'il ne s'inscrit pas automatiquement, mais il conserve certaines choses synchronisées et entraînera également des erreurs de compilation si vous n'ajoutez que sur les mappages et non la fonction dans le fichier source.
mappings.h: p> PARSER.H: P> void Myclass::dispatch(string cmd, string args) {
if (cmd == "")
// handle empty case
#define UGLY_SUCKER( a, b, c ) else if (cmd == a) b( args )
#include Mappings.h
#undef UGLY_SUCKER
else
cmd_default(args);
}
void Myclass::printOptions() {
#define UGLY_SUCKER( a, b, c ) std::cout << a << \t << c << std::endl
#include Mappings.h
#undef UGLY_SUCKER
}
void Myclass::cmd_foo(string args) {
...
}
Bien, bien accordé, c'est moche, mais il semble couper les répétitions à deux. Mais un #include au milieu du code est vraiment laid. +1
+1, pour la même raison. En outre, en supposant que chaque commande "FOO" entraîne appel à CMD_FOO, avec un peu de stringification, vous pouvez éviter la répétition dans les paramètres.
Oui, je pense dans les lignes de l'opérateur "Coller".
La solution de base, par mon lien dans le commentaire de la question, est de mapper une chaîne à un appel de fonction de quelque sorte.
Pour enregistrer réellement la chaîne -> Pointeur de fonction / paire de fonctions / Fonction: p>
Premièrement, avez un singleton (choc! Horreur!) Objet du répartiteur.
Appelons-le TheDispatcher - c'est une enveloppe pour un Puis, avez une classe de registre: p> maintenant dans vos unités de compilation individuelles que vous créez.
Objets statiques (choc! Horreur!): P> mappe Register r1_( "hello", DoSayHello );
Vous devrez au moins définir les fonctions et les ajouter à un registre. (S'ils doivent être des fonctions des membres non lignes de certaines catégories, vous devrez également les déclarer.) Autre que certaines langues spécifiques à un domaine génèrent le code actuel (comme CJHUITT'S MACRO HACKERY ), je ne vois aucun moyen de mentionner ces fonctions deux (ou trois) fois. p>
Oui, je pense que j'ai finalement dans mon crâne épais.
Cette question a été posée à plusieurs reprises et a répondu par moi ici Stackoverflow.com/Questtions/659581/...
Il demande également un système d'inscription de quelque sorte de réduire les efforts déployés dans le maintien du dictionnaire.
Il est, mais je ne pense pas qu'il y ait un qui le satisferait. Vous pourriez faire quelque chose de brutal et de moche avec des macros, mais c'est plus de problèmes que ça vaut la peine.