[Modifier] Ceci est une réponse à la question originale, non éditée de l'auteur qui était en fait deux questions.
Je dois admettre que cette syntaxe est fortement déroutant pour moi. Comment cela peut-il être légal C++? :) Yat-il un truc sous le capot? Cette syntaxe est-elle documentée quelque part?
Ceci est parfaitement légal et n'est en fait pas trop compliqué.
template <class T>
class C
{
public:
T* function_pointer;
};
void fn(int x)
{
cout << x << endl;
}
int main(int argc, char** argv)
{
C<void (int x)> c;
c.function_pointer = &fn;
c.function_pointer(123); // outputs x
}
Il est fondamentalement la même chose que faire:
typedef void Function(int);
C<Function> c;
Ce type est non seulement applicable C++, il est tout aussi applicable dans C (le type réel C est paramétrées). Le modèle magique ici prend quelque chose comme la fonction typedef ici et étant capable de détecter les types de valeurs et d'arguments de retour. Expliquer que cela serait trop long ici et boost :: function utilise beaucoup de meta-templates de traits de fonction dans boost pour récupérer cette information. Si vous voulez vraiment passer du temps à apprendre cela, vous devriez essayer de comprendre l'implémentation de boost en commençant par boost :: function_traits dans Boost.Type Traits.
Cependant, je veux résoudre votre problème général. Je pense que vous essayez trop de simplifier quelques lignes de code parfaitement acceptable. Il n'y a rien de mal à passer les arguments de vos sous-classes de commande à travers leurs constructeurs de sous-classes paramétrés. Est-ce que ça vaut vraiment la peine d'essayer d'impliquer des typelists et de booster des solutions de type: function, augmentant ainsi les temps de compilation et la complexité du code, juste pour ça?
Si vous voulez réduire davantage, il suffit d'écrire une fonction Execute qui exécutera une sous-classe de commande et l'ajouter à la pile undo et ainsi de suite:
typedef boost::shared_ptr<Command> CommandPtr;
void execute(const CommandPtr& cmd)
{
cmd->execute();
// add command to undo stack or whatever else you want to do
}
// The client can simply write something like this:
execute(CommandPtr(new CmdAdd(some_value));
Je pense vraiment que le compromis d'essayer pour le rendre plus compliqué ne vaut pas la peine. Les auteurs de boost voulaient écrire une solution extrêmement générale pour boost :: function qui serait utilisée par de nombreuses personnes sur de nombreuses plateformes et compilateurs. Cependant, ils n'ont pas essayé de généraliser un système de commande capable d'exécuter des fonctions avec des signatures différentes à travers un système d'annulation unifié (nécessitant ainsi que l'état de ces commandes soit préservé même après avoir fini de les appeler et être capable d'annuler et re -exécute-les sans spécifier à nouveau les données d'état d'origine sur les exécutions suivantes). Pour cela, votre approche basée sur l'héritage est probablement la meilleure et la plus directe.
Veuillez poser une seule question par question - si vous avez deux questions à poser, soumettez deux questions distinctes. – bdonlan
Vrai, désolé, je ne le ferai plus – Dinaiz
Vous pouvez éditer votre question pour supprimer l'une des questions pour la diviser en une autre question - il est difficile de répondre comme ça parce que si quelqu'un ne connaît que la réponse à l'une de vos questions , ils seront réticents à soumettre une réponse. – bdonlan