2012-08-15 1 views
0

J'ai déjà demandé a similar question here, mais je n'ai pas vraiment eu la réponse que je voulais parce que ma question était mal formulée et les exemples étaient mauvais. Donc, je donne un autre coup de feu, avec une meilleure explication et un meilleur code.Mélanger le modèle de commande, le modèle d'usine et les modèles tous ensemble ...

Le code ci-dessous a été retiré des détails inutiles mais cela fonctionne. La chose est que je voudrais utiliser la déduction d'argument de modèle, si possible, pour simplifier l'appel de fonction de modèle.

J'ai une usine qui crée des commandes. Pour créer une commande, j'utilise un appel comme celui-là:

mCommandFactory.createCommand< 
         DoSomeStuff, 
         ParameterType1, 
         ParameterType2, 
         ParameterType3, 
         ParameterType4 
         > 
         (std:string("some description"), 
         parameter1, 
         parameter2, 
         parameter3, 
         parameter4); 

Comme vous l'avez sans doute deviné, le type de paramètre1 est ParameterType1, et ainsi de suite ....

Maintenant, si nous regardons la définition de la commande - DoSomeStuff- lui-même:

class DoSomeStuff : public UndoableCommand< ParameterType1 , ParameterType2, ParameterType3 , ParameterType4 > 
    { 
    public: 
     DoSomeStuff(... /* arguments which are needed for precessing the command and undoing it*/); 
     ~DoSomeStuff() throw(); 
     void executeImpl(); 
     void undoImpl(); 

    protected: 
       ... /* members which are needed for precessing the command and undoing it*/ 
    }; 

Comme vous pouvez le voir, l'information ParameterTypeN est déjà à l'intérieur déclaration DoSomeStuff.

Je me demandais s'il était possible d'une certaine manière de remplacer l'appel CreateCommand ci-dessus par quelque chose de plus simple:

mCommandFactory.createCommand<DoSomeStuff> 
         (std:string("some description"), 
         parameter1, 
         parameter2, 
         parameter3, 
         parameter4); 

Voici le code CommandFactory:

class CommandFactory 
    { 
    private: 
      // some stuff used to initialize objects created by this factory 

    public: 
     CommandFactory(...) : ... /* members initialization */ 

     { 
     } 


     template <class CommandType, typename P1, typename P2, typename P3, typename P4> 
     void createCommand(juce::String& description,P1 p1, P2 p2, P3 p3, P4 p4) 
     { 
      Undoable* cmdPtr = new CommandType(p1, p2, p3, p4); 
      ... 
      // init cmdPtr 

      (*cmdPtr)();    
     } 

Fondamentalement, le point serait de déplacer la complexité dans CommandFactory, pour garder le "code client" (l'appel à createCommand) aussi simple et court que possible.

Des idées?

Répondre

1

Je ne suis pas certain de comprendre correctement la question, mais cela devrait fonctionner.

template<typename ParameterType1 , typename ParameterType2, typename ParameterType3 , typename ParameterType4> 
class UndoableCommand 
{ 
public: 
    UndoableCommand(ParameterType1 p1, ParameterType2 p2, ParameterType3 p3, ParameterType4 p4) 
    {} 
}; 

class DoSomeStuff : public UndoableCommand< int ,double, std::string , int> 
{ 
public: 
    DoSomeStuff(int p1, double p2, std::string p3, int p4) 
     :UndoableCommand(p1,p2,p3,p4) 
    {} 
}; 

class CommandFactory 
{ 
public: 
    CommandFactory() 
    {} 

    template <class CommandType, typename P1, typename P2, typename P3, typename P4> 
    void createCommand(std::string& description,P1 p1, P2 p2, P3 p3, P4 p4) 
    { 
     UndoableCommand<P1,P2,P3,P4> * cmdPtr = new CommandType(p1, p2, p3, p4); 

    } 
}; 

Utilisé en tant que tels

CommandFactory fact; 
fact.createCommand<DoSomeStuff>(std::string("description"),1,2.0,std::string("3"),4); 
0

Oui, vous pouvez le remplacer par quelque chose de plus simple. Avez-vous considéré std::bind? Une fois que vous l'avez modifié pour utiliser <function>, votre classe DoSomeStuff sera juste une structure qui contient une paire de std::function s.

+0

Je ne suis pas sûr ... J'utilise beaucoup bind & functions dans le reste du code, mais pour la liaison dynamique. Ici, tout est connu au moment de la compilation. Peut-être que je néglige complètement votre point. J'ai besoin d'un exemple simple pour voir comment vous utiliseriez des foncteurs pour résoudre ce problème particulier ... – Dinaiz

0

Vous pouvez faire des typedefs de types de paramètres à la classe Commandtype, et ainsi résoudre les types de paramètres dans la fonction createCommand sans les ajouter explicitement en tant que paramètres de modèle. Pour que cela se produise, vous pouvez faire typedefs de paramètres de modèle passés à UndoableCommand à l'intérieur de cette classe.

1

Vous n'avez pas besoin de quelque chose de spécial ici, votre approche mCommandFactory.createCommand<DoSomeStuff>(...); doit travailler. Le compilateur déduira automatiquement les types d'arguments donnés de l'expression d'appel de fonction et instanciera correctement le modèle createCommand<>.

+0

C'est embarrassant. Vous avez absolument raison.Cela n'a pas fonctionné avant, mais pour une raison totalement irréalisée que j'avais fixée sans m'en rendre compte. Je ne sais pas quoi faire pour la prime. Vous et le blaireau les audacieux ont tous les deux raison. Cela vous dérange-t-il si je le lui donne, car il a une réputation inférieure à vous? – Dinaiz

+1

Votre prime - vos règles :-) – Rost

Questions connexes