IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Chaine d'instructions configurable


Sujet :

C++

  1. #1
    Membre très actif
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Par défaut Chaine d'instructions configurable
    Bonsoir, j'aimerais mettre en place une chaîne d'instructions comme dans un algorithme classique mais de manière à être configurable dans un fichier texte;

    par exemple, pouvoir faire (en pseudo-code):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
     
    //création d'objets
    create C1 object c1;
    create C2 object c2;
    create C3 object c3;
     
    //appels de méthodes
    call method m1 on object c1;
    call method m2 on object c2;
     
    //branchement
    if (condition) then { call method m3 on object c3; }
    else  { call method m1 on object c1; }
     
    //parcours de liste
    for(i=; i<100; ++i)
      call method m2 on object c2;
    etc...

    ce pseudo-code sera "traduit en classes" au chargement

    en gros, enchaîner des instructions très basiques que je puisse ajouter ou retirer à la volée

    Pour l'instant j'ai en tête une classe de base "TasksChain" dont dérivent 3 classes filles :

    1. une classe "TasksList" pour traiter une suite d'appels de méthodes : je stocke les foncteurs correspondants dans un std::vector que je parcours ensuite; cette classe a un pointeur sur une autre instance de
      TasksChain
    2. pour les branchements j'ai pensé à une classe "TaskConditional" avec pour chaque possibilité (stockées dans une std::map) un pointeur sur une autre instance de TasksChain
    3. enfin pour les boucles une classe "TasksLoop" qui pointe sur une TasksList qui sera exécutée un nombre n de fois


    Cette organisation vous semble-t-elle pertinente ?

    sinon existe-il déjà des solutions ou des libs disponibles ?

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    En fait, je ferais sans doute une classe de base Task, avec un seule fonction (en dehors des constructeurs et destructeurs ) virtuelle pure : execute.

    A partir de là, pour chaque foncteur, il y aurait une classe qui hérite de cette classe de base, et, pour les "bloc d'instructions" comme les boucle et autres tests, on se baserait meme sur un pattern proche du composite.

    La tache qui servirait pour les tests pourrait en effet ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    class Task
    {
        public:
            virtual ~Task(){}
            virtual void execute() = 0;
    }
    class Test : public Task
    {
        public:
            Test(Functor * fun):fun_(fun){}
            virtual void execute()
            {
                if(fun() )
                    executeAll(true_.begin(),true_.end());
                else
                    executeAll(false_.begin(),false_.end());
            }
        private:
            template <typename iterator>
            void executeAll(iterator begin, iterator end)
            {
                 while(begin!:end)
                 {
                      (*begin)->execute();
                      ++begin;
                 }
            }
            std::vector<Task*> true_;
            std::vector<Task*> false_;
    };
    Après, vient le problème du parsing et de la compréhension du fichier texte dans lequel le "script" est défini
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre très actif
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,

    En fait, je ferais sans doute une classe de base Task, avec un seule fonction (en dehors des constructeurs et destructeurs ) virtuelle pure : execute.

    A partir de là, pour chaque foncteur, il y aurait une classe qui hérite de cette classe de base, et, pour les "bloc d'instructions" comme les boucle et autres tests, on se baserait meme sur un pattern proche du composite.

    La tache qui servirait pour les tests pourrait en effet ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    class Task
    {
        public:
            virtual ~Task(){}
            virtual void execute() const = 0;
    }
    class Test : public Task
    {
        public:
            Test(Functor * fun):fun_(fun){}
            virtual void execute() const
            {
                if(fun() )
                    executeAll(true_.begin(),true_.end());
                else
                    executeAll(false_.begin(),false_.end());
            }
        private:
            template <typename iterator>
            void executeAll(iterator begin, iterator end) const
            {
                 while(begin!:end)
                 {
                      (*begin)->execute();
                      ++begin;
                 }
            }
            std::vector<Task*> true_;
            std::vector<Task*> false_;
    };
    Après, vient le problème du parsing et de la compréhension du fichier texte dans lequel le "script" est défini
    je vois , mais pour qu'il y ait chaine, il faut bien que Task pointe sur une autre Task, non ?

  4. #4
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Bonsoir,

    Pour ce dont te parle Koala, tu devrais trouver des ressources à l'aide des mots clés "Design Pattern Interpreter".

    C'est pas très complexe à mettre en place, mais "chiant" (C++ seul est pauvre au runtime)

    Tu n'as pas la possibilité d'utiliser un langage existant (python, ECMAScript, etc) qu'il te suffirait d'étendre?

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par coda_blank Voir le message
    je vois , mais pour qu'il y ait chaine, il faut bien que Task pointe sur une autre Task, non ?
    Pas forcément...

    Tu rajoutes ton pointeur vers une tache dans n'importe quelle collection de la STL (ex : j'ai utilisé un std::vector<Task*> pour true_ et false_ ) et tu parcoure cette collection élément par élément

    Ta liste de taches ressemblerait alors à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class TaskList
    {
       public:
           ~TaskList(){clear();}
           void addTask(Task * toAdd){tasks_.push_back(toAdd);}
           void execute() const
           {
               for(std::vector<Task*>::const_iterator it=tasks_.begin()
                   it!=tasks_.end();++it)
                   (*it)->execute();
           }
           void clear()
           {
               for(std::vector<Task*>::const_iterator it=tasks_.begin()
                   it!=tasks_.end();++it)
               {
                    delete (*it);
                }
                tasks_.clear();
           }
        private:
           std::vector<Task*> tasks_;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Les exemples que je donne ne sont effectivement que minimaux, et donc incomplets...

    Mais, si tu rajoute une fonction addTask(Task * , bool ifTrue) qui permet de rajouter, en fonction de la valeur de ifTrue, une tache à la liste des taches à effectuer à la classe Test que je t'ai présentée plus tot, tu crée ton test, tu le remplis des taches à effectuer si le test renvoie vrai et de celles à effectuer si le test renvoie faux, puis tu ajoute le test à ta liste de taches à effectuer...

    Idem pour tout ce qui serait boucle

    Au final, une fois que toutes les taches sont créées (et placées à la bonne place, il suffit d'appeler la fonction execute de ta liste de tache pour que toutes les taches soient effectuées et que, s'il s'agit d'effectuer une boucle ou un test, on prenne l'embranchement correspondant, ou que l'on exécute l'ensemble des taches en boucle
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre très actif
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Par défaut
    Citation Envoyé par bretus Voir le message
    Bonsoir,

    Pour ce dont te parle Koala, tu devrais trouver des ressources à l'aide des mots clés "Design Pattern Interpreter".

    C'est pas très complexe à mettre en place, mais "chiant" (C++ seul est pauvre au runtime)

    Tu n'as pas la possibilité d'utiliser un langage existant (python, ECMAScript, etc) qu'il te suffirait d'étendre?
    Interpeter c'est trop lourd par rapport à ce que je veux faire; j'ai juste besoin d'alias dans un fichier texte pour instancier quelques classes foncteurs

    alors bien sûr un langage de script serait l'idéal mais il a l'inconvénient de la lenteur, même compilé, et je dois exécuter des instructions simples plusieurs dizaines de milliers de fois par secondes

    sans compter que ça rajoute une dépendance au projet et que les bindings ne sont pas toujours très bien suivis

  8. #8
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Désolé, mais j'ai du mal à percevoir la différence entre ce que tu veux et un moteur de script. Je me demande donc en quoi ça sera plus rapide qu'un autre moteur de script?

    Le fait que tu ais de la conditionnelle dans ton fichier texte me laisse penser qu'il te faut évaluer des expressions avant de lancer l'exécution de tes listes de tâches.

    Je ne vois que de la compilation à la volée à la rigueur pour y échapper (fichier texte => plugin => chargement et exécution)...

    C'est ça que tu entends par "traduit en classes"?

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Citation Envoyé par bretus Voir le message
    Désolé, mais j'ai du mal à percevoir la différence entre ce que tu veux et un moteur de script. Je me demande donc en quoi ça sera plus rapide qu'un autre moteur de script?
    Parce qu'il créera sa chaîne de tâches à l'initialisation, en lisant le fichier texte et en créant des objets C++ qui vont l'exécuter, puis il va l'exécuter plein de fois sans relire le fichier texte. C'est une sorte de compilation.

    Les langages modernes comme python stockent le pseudo code pour gagner du temps d'exécution, mais ça ne sera pas aussi performant que ce qu'il cherche.

  10. #10
    Membre très actif
    Profil pro
    Dev
    Inscrit en
    Mai 2009
    Messages
    257
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Mai 2009
    Messages : 257
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Parce qu'il créera sa chaîne de tâches à l'initialisation, en lisant le fichier texte et en créant des objets C++ qui vont l'exécuter, puis il va l'exécuter plein de fois sans relire le fichier texte. C'est une sorte de compilation.

    Les langages modernes comme python stockent le pseudo code pour gagner du temps d'exécution, mais ça ne sera pas aussi performant que ce qu'il cherche.
    voilà, c'est exactement ça

Discussions similaires

  1. [AC-2003] Executer une instruction depuis une variable chaine
    Par JYL74 dans le forum VBA Access
    Réponses: 7
    Dernier message: 27/09/2010, 14h18
  2. transformer une chaine en instruction
    Par dom_dev dans le forum ActionScript 1 & ActionScript 2
    Réponses: 2
    Dernier message: 06/07/2009, 10h56
  3. [BO XIr2]Instruction de chaine
    Par luc_chivas dans le forum Deski
    Réponses: 1
    Dernier message: 13/11/2008, 13h16
  4. Réponses: 2
    Dernier message: 01/12/2006, 14h50
  5. Configuration des chaînes incorrecte
    Par gege2061 dans le forum Applications et environnements graphiques
    Réponses: 9
    Dernier message: 06/06/2006, 10h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo