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 :

Invoquer un template d'enum


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 Invoquer un template d'enum
    Bonjour à tous,

    J'ai deux enums comme ceci :
    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
    enum E_COL
    {
       E_COL_0,
       E_COL_1,
       E_COL_2;
       E_COL_COUNT
    };
     
    enum E_ROW
    {
       E_ROW_0,
       E_ROW_1,
       E_ROW_2;
       E_ROW_COUNT
    };
    Ainsi qu'une classe template comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<E_COL COL, E_ROW ROW>
    class CColRowHelper
    {
    	enum { activated = false };
            static void DoSomething() {}
    };
    Lorsque je veux activer un point, il me faut spécialiser cette classe template. Par exemple, la colonne 1 avec la row 2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<> CColRowHelper<E_COL_1, E_ROW_2>
    {
    	enum { activated = true };
            static void DoSomething() { /* it does something */ }
    };
    A l'initialisation, toute association colonne / row étant marquée comme "activée", il faut que j'exécute la méthode "DoSomething()"

    Pour le moment, je ne vois qu'une solution, mais pas mal contraignante, qui serait de répertorier toutes les associations possibles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if(CColRowHelper<E_COL_0, E_ROW_0>::activated)
        CColRowHelper<E_COL_0, E_ROW_0>::DoSomething()
     
    if(CColRowHelper<E_COL_0, E_ROW_1>::activated)
        CColRowHelper<E_COL_0, E_ROW_1>::DoSomething()
    N'y aurait-il pas un moyen de faire quelque chose de ce style ? :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for(int col = 0; col < E_COL_COUNT; ++col)
        for(int row = 0; row < E_ROW_COUNT; ++row)
            if(CColRowHelper<col, row>::activated)
                CColRowHelper<col, row>::DoSomething();
    Merci à vous,
    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 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    pourquoi ne pas utiliser un simple tableau ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class CColRowHelper
    {
    public:
    	bool activated;
            static void DoSomething() {}
    };
    CColRowHelper* ColRowTab[E_COL_COUNT*E_ROW_COUNT];
    CColRowHelper* GetColRow(E_COL col, E_ROW row)
    {
       return ColRowTable[col*E_COL_COUNT+row];
    }
    Après tu es libre de bidouiller des fonctions autour de ça.
    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
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Les templates sont évaluées à la compilation, le for à l'exécution.
    Mais il est possible de passer outre : https://github.com/Ekleog/misc/blob/master/tplfor.cpp
    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
     
    template <int Col, int RFrom, int RTo, template <int, int> class Call>
    struct ForRow {
        static void run() {
            Call<Col, RFrom>::run();
            ForRow<Col, RFrom + 1, RTo, Call>::run();
        }
    };
    template <int Col, int REnded, template <int, int> class Call>
    struct ForRow<Col, REnded, REnded, Call> {
        static void run() { }
    };
     
    template <int CFrom, int CTo, int RFrom, int RTo, template <int, int> class Call>
    struct For {
        static void run() {
            ForRow<CFrom, RFrom, RTo, Call>::run();
            For<CFrom + 1, CTo, RFrom, RTo, Call>::run();
        }
    };
    template <int CEnded, int RFrom, int RTo, template <int, int> class Call>
    struct For<CEnded, CEnded, RFrom, RTo, Call> {
        static void run() { }
    };
     
    // Pour tester la compilation
    #include <cstdio>
    template <int Col, int Row> struct CColRowHelper {
        enum { activated = true };
        static void DoSomething() { std::printf("."); }
    };
    template <> struct CColRowHelper<5, 5> {
        enum { activated = false };
        static void DoSomething() { }
    };
     
    // Le foncteur
    template <int Col, int Row>
    struct IfActDoSth {
        static void run() {
            if (CColRowHelper<Col, Row>::activated)
                CColRowHelper<Col, Row>::DoSomething();
        }
    };
     
    // Et l'appel
    void DoTheSths() {
        For<0, 10, 0, 10, IfActDoSth>::run();
        // Lance IfActDoSth::run() pour 0,1,2,3,4,5,6,7,8,9 en ligne et idem pour
        // les colonnes.
    }
     
    // Un main de test
    int main(int, char**) {
        DoTheSths();
    }
    Au passage, si tu définis CColRowHelper comme tu nous l'as annoncé, alors le test de if (...::activated) est inutile : dans le cas contraire, DoSomething ne fait rien.

  4. #4
    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
    Citation Envoyé par Ekleog Voir le message
    Au passage, si tu définis CColRowHelper comme tu nous l'as annoncé, alors le test de if (...::activated) est inutile : dans le cas contraire, DoSomething ne fait rien.
    Merci Ekleog, j'ai fait comme ça et ça fonctionne bien

    En revanche, le test de "if (CColRowHelper<Col, Row>::activated)" à la ligne 41 qui est définit dans le foncteur, serait-il possible de le déplacer dans l'enchaînement des templates ?

    Etant donné que c'est connu à la compilation, autant le gérer à la compilation non ?

    C'est pas grand chose mais ce test va être exécuté des milliards de fois, alors j'imagine que ça aura un bon impact se l'ensemble..

    Merci encore
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  5. #5
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Même exécuté des milliards de fois, un compilateur sera toujours assez intelligent pour optimiser ... Parce qu'un if(1) goto a; else goto b; ce n'est pas trop dur à optimiser, hein. Surtout vu qu'il n'y a même pas de else !
    Enfin, sauf peut-être si tu donnes -O0 !

    EDIT : Petit test (en C pour rendre l'assembleur plus compréhensible, mais c'est tout pareil en C++) avec -O[0, 1, 2, 3] :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <stdio.h>
    int main() {
      if (1) {
        printf("1");
      } else {
        printf("0");
      }
      return 0;
    }
    Résultats :

    D'abord, une remarque : -O2 et -O3 donnent les mêmes résultats.

    Maintenant, le désassemblage (je ne me préoccupe que du main) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // -O0
       0x00000000004004e4 <+0>:     push   rbp
       0x00000000004004e5 <+1>:     mov    rbp,rsp
       0x00000000004004e8 <+4>:     mov    edi,0x31
       0x00000000004004ed <+9>:     call   0x4003e0 <putchar@plt>
       0x00000000004004f2 <+14>:    mov    eax,0x0
       0x00000000004004f7 <+19>:    pop    rbp
       0x00000000004004f8 <+20>:    ret
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // -O1
       0x00000000004004e4 <+0>:     sub    rsp,0x8
       0x00000000004004e8 <+4>:     mov    edi,0x31
       0x00000000004004ed <+9>:     call   0x4003e0 <putchar@plt>
       0x00000000004004f2 <+14>:    mov    eax,0x0
       0x00000000004004f7 <+19>:    add    rsp,0x8
       0x00000000004004fb <+23>:    ret
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // -O2 (= -O3)
       0x0000000000400400 <+0>:     sub    rsp,0x8
       0x0000000000400404 <+4>:     mov    edi,0x31
       0x0000000000400409 <+9>:     call   0x4003e0 <putchar@plt>
       0x000000000040040e <+14>:    xor    eax,eax
       0x0000000000400410 <+16>:    add    rsp,0x8
       0x0000000000400414 <+20>:    ret
    Il reste quelques différences, mais un point commun est décelable : à aucun niveau il n'y a de saut (aucune instruction j**).

    Donc, même avec -O0, l'optimisation se fait !

Discussions similaires

  1. Classe template et enum T
    Par Daikyo dans le forum Langage
    Réponses: 4
    Dernier message: 06/12/2010, 19h12
  2. enum et template
    Par camboui dans le forum Langage
    Réponses: 12
    Dernier message: 21/11/2009, 11h01
  3. Spécialisation de template parametre avec Enum
    Par 3DArchi dans le forum Langage
    Réponses: 4
    Dernier message: 24/09/2008, 15h21
  4. [XSLT] invoquer un template d'un autre fichier
    Par vpet dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 14/12/2006, 13h48

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