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 :

Statique VS dynamique


Sujet :

C++

  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut Statique VS dynamique
    Bonjour à tous,

    Je me casse les dents sur un truc que je pensais bateau à la base mais que finalement me donne du fil à retordre.

    Le contexte est que j'ai plusieurs algorithmes qui agissent sur le même contexte, mais de manière différente.

    Les codes ci dessous ne sont pas validés syntaxiquement, car à "main levé", mais c'est pas grave, l'idée reste la même.

    La définition d'un algorithme ressemble à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template<int I> class MonAlgo
    {
       static bool Do(); // renvoi true s'il a pu améliorer quelque chose, sinon false
    }
    Ici l'énumération des algorithmes disponibles :
    enum E_ALGOS
    {
    MON_ALGO_1,
    MON_ALGO_2,
    MON_ALGO_3,
    MON_ALGO_4
    }

    Donc l'implémentation d'in algo se résume à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template<> MonAlgo<MON_ALGO_1> {
       static bool Do() {
          // Je fais des trucs
          // Si j'ai assuré, return true sinon return false
       }
    };
    Désormais, il faut les faire coucher ensemble, sachant que l'ordre d'exécution est un facteur important au niveau des performances. Alors je veux un système semi configurable par le code qui pourra décrire un ordre d'exécution. Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int Exec_Table = [
       MON_ALGO_1,
       MON_ALGO_3,
       MON_ALGO_4,
       MON_ALGO_1,
       MON_ALGO_2,
       MON_ALGO_4
    ];
    Un autre cheminement pourrait donner :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int Exec_Table = [
       MON_ALGO_2,
       MON_ALGO_1,
       MON_ALGO_3,
       MON_ALGO_4,
       MON_ALGO_3,
       MON_ALGO_4
    ];
    Toutes ces valeurs sont statiques, alors j'avais espéré pouvoir obtenir une programmation statique, ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for(int i = 0, i < sizeof(Exec_Table); ++i) {
       bool b = true;
       while(b = Exec_Table<i>::Do()) {} // On le ré exécute jusqu'à temps qu'il ne puisse plus offre de solution
    }
    Mais une erreur de compilation m'empêche de faire ceci en m'indiquant que "i" n'est pas statique, ce qui peut se comprendre.

    Première question : Etant donné que tout est basé sur du statique, comment faire en sorte que ça le reste dans cette portion de code, et donc que ça compile ?

    Maintenant deuxième demande : Je souhaite faire des combinaisons d'algos, à savoir par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    MON_ALGO_1
       MON_ALGO_3
       MON_ALGO_4
    C'est à dire que tant que 3 ou 4 on trouvé un résultat, ce couple doit être ré exécuté jusqu'à tant que ni l'un ni l'autre ne renvoi du positif. Si tel est le cas, on réexécute 1 et si ce dernier trouver quelque chose, on relancer le couple. Le tout s'arrête lorsque 1 ne trouve pas de solution meilleure et que donc il n'y a plus besoin d'exécuter 3 et 4.

    J'espère trouver un moyen de faire en sorte que le cheminement soit configurable dans le code, via des tableaux et que le compilateur puisse gérer ça si tant est que l'ensemble soit programmée de manière statique. Mais là je galère un peu comme vous pouvez le constater.

    Le premier début de réponse serait de répondre à la première question, à savoir comment rendre ce "i" constant sachant qu'il démarre de 0, valeur constante jusqu'à sizeof(tab) valeur également constante.

    Merci beaucoup par avance,

    A bientôt
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Salut,

    effectivement puisque ton i prend sa valeur à l'exécution tu n'y arriveras pas.
    Un moyen pourrait être d'utiliser des variadic templates pour appeler tes algos Call(Algo1, Algo2, ...); Call(Algo2, Algo3, ...);, je promets rien, mais je pense que ça devrait marcher.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Une utilisant spécifiquement un tableau pour stocker l'ordre de tes algos je sais pas si c'est possible (peut être à base de constexpr ?).

    Si tu peux les passer en paramètre template (à priori pas de soucis, c'est des constantes de compilation), tu peux faire quelque chose du genre
    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
    #include <initializer_list>
    #include <iostream>
     
    enum E_ALGOS {
    	MON_ALGO_1,
    	MON_ALGO_2
    };
     
    template<int I> struct Exec { };
    template<> struct Exec<MON_ALGO_1> { static bool Do() { std::cout << "1\n"; return true; } };
    template<> struct Exec<MON_ALGO_2> { static bool Do() { std::cout << "2\n"; return true; } };
     
    template <int I> struct Run { static void Do() { while(!Exec<I>::Do()); } };
     
    template <int... I>
    void foo() {
    	// à base d'initializer_list, ordre garanti
    	auto list = { (Run<I>::Do(), 0)... };
     
    	// à base de lambda, ordre non garanti
    	[](...){ }((Run<I>::Do(), 0)...);
    }
     
    int main() {
    	foo<MON_ALGO_1, MON_ALGO_2>();
    }

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Je ne vois pas pourquoi tu veux obligatoirement du static ?

    Je vois 2 solutions une pure C avec des #define (<- avec cette solution je vais prendre des -1 ) et une avec un foncteur

    Solution 1:
    Tu peux mettre tout dans un fichier algos.h pour l'inclure là où tu veux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #define ALGO_1 \
         \
        /* XXX */
     
    #define ALGO_2 \
         \
        /* XXX */
    Et plus loin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //  maybe include "algos.h"
     
    //  Définition de ton contexte ici
    //  int i = 0;
     
        ALGO_2
        ALGO_1
    //  ...
    Solution 2:
    Édit: On fait un tableau de pointeurs de fonctions et ainsi supprimer le switch/ case. Mais tous tes algos doivent avoir la même signature.

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    class Algos {
    // Constructor
    public:
     
        Algos() : current_nb_algos(0) {}
     
     
    // Public Interface
    public:
     
        void set_nb_algos(unsigned short new_number) {
            if (new_number > current_nb_algos) {
                list_algos.reserve(new_number);
            }
     
            if (new_number > 0) { current_nb_algos = new_number; }
        }
     
     
        void add_algo(ALGO_ID algo) {
    //      maybe if (algo < NB_ALGOS)
            list_algos.push_back(algo);
        }
     
     
    //  void add_algo(unsigned short nb_algos, ALGO_ID algo, ...) { /* */ }
     
     
    public:
     
        void operator() () {
    //      Soit tous les algos peuvent être inline
    //      Ou alors on code les algos dans le switch case
    //      Ou un autre truc
     
            std::vector<ALGO_ID>::iterator it = list_algos.begin();
     
            for(unsigned nb = 0; ((nb < current_nb_algos) && (it != list_algos.end())); ++it, ++nb) {
                switch(*it) {
                case ALGO_1:
    //             algo_1();
    //             or
    //             /* XXX */
                    break;
     
                case ALGO_2:
    //             algo_2();
    //             or
    //             /* XXX */
                    break;
     
                case ALGO_3:
    //             algo_3();
    //             or
    //             /* XXX */
                    break;
                }
            }
        }
     
     
    public:
     
        typedef enum e_ALGO_ID {
            ALGO_1 = 0,
            ALGO_2,
            ALGO_3,
            NB_ALGOS
        } ALGO_ID;
     
     
    private:
     
        std::vector<ALGO_ID> list_algos;
     
        unsigned current_nb_algos;
    };

  5. #5
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Ouais finalement autant se passer du statique, c'est pas ça qui va faire rallonger significativement les performances pour mon problème et ça sera plus facile à gérer le point numéro 2.

    C'était au cas où un truc statique était possible sans trop se casser la tête

    Merci à vous,

    A bientôt
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Tout problème en informatique peut être résolut en ajoutant un niveau d'indirection
    Ce n'est pas de moi, mais en voici encore une fois la preuve

    Il y a, en effet, tout à fait moyen de gérer les algorithmes à la compilation à l'aide des variadic template à la condition expresse que tu puisse savoir, à la compilation, dans quel ordre il faudra les exécuter

    Partons donc d'une légère adaptation de ta classe MonAlgo, pour qu'elle prenne la forme d'un foncteur (c'est, tout simplement, plus facile à manipuler ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template <int i>
    struct MonAlgo{
        enum{value = i};
        bool operator()() {
            std::cout<<"callee called with value"<<value<<"\n";
            return true;
        }
    };
    Puis, créons un autre foncteur qui utilise les variadic templates pour savoir quels algorithmes il doit appeler sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template <int i, int ... others>
    struct Caller{
        bool operator()() const{
            bool b =MonAlgo<i>()();  //appelle effectivement l'algorithme
            if(b)
                return Caller<others ...>()(); // déroule les algorithmes suivants
            return false;
        }
    };
    Il n'y a plus qu'à mettre fin à la récursion en spécialisant Caller sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template <int i>
    struct Caller<i>{
        bool operator()()const{
            return MonAlgo<i>()();
        }
     
    };
    Une fois cela fait, il n'y a plus qu'à créer notre fonction main :
    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
    /* l'énumération que nous allons utiliser */
    enum E_ALGO{
        MON_ALGO_1 = 1,
    MON_ALGO_2 ,
    MON_ALGO_3,
    MON_ALGO_4
    };
    int main(){
        Caller<
        MON_ALGO_1,
        MON_ALGO_2,
        MON_ALGO_3,
        MON_ALGO_4>()();
        return 0;
    }
    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

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Site statique et dynamique
    Par tnounou82 dans le forum Dépannage et Assistance
    Réponses: 2
    Dernier message: 23/04/2007, 12h58
  2. [RegEx] Trouver les appels statique et dynamique d'une class
    Par jeff_! dans le forum Langage
    Réponses: 8
    Dernier message: 07/04/2006, 16h31
  3. Agrégation: statique ou dynamique
    Par icer dans le forum C++
    Réponses: 13
    Dernier message: 04/03/2006, 15h48
  4. char *, string et tableau statique ou dynamique
    Par salseropom dans le forum C
    Réponses: 2
    Dernier message: 05/12/2005, 11h33
  5. Réponses: 2
    Dernier message: 19/08/2005, 16h02

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