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 :

macro qui crée enum et tableau


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut macro qui crée enum et tableau
    Bonjour,

    J'ai trois structures :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct Cat { const static unsigned mask = 1; };
    struct Dog { const static unsigned mask = 2; };
    struct Cow { const static unsigned mask = 4; };
    J'aimerais créer une macro qui prendrait des types en argument et qui :
    - en ferait un enum
    - créerait un tableau avec les maks des types

    Rien compris ? X) Un petit exemple sera plus parlant. J'aimerais pouvoir écrire :

    Ceci me créerait une structure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct
    {
        enum {Dog,Cow,Cat};
        unsigned tab[3] = {2,4,1};
    } test;
    Pour l'instant j'ai écrit la macro suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #define macro(Ts...)                    \
    struct                                  \
    {                                       \
        enum { Ts,count };                  \
        unsigned tab[count] = {Ts::mask};   \
    } test;
    C'est bon pour l'enum, mais pour tab c'est pas encore ça il doit y avoir un problème d'expanded pack quelque part, mais je ne sais pas comment résoudre ça !

    Des suggestions ?
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Proposition au pif (car n'aimant pas les macros, je ne connais pas ce niveau de détails):
    As-tu essayé Ts...::mask et Ts::mask... et aucun des deux ne marchent?

    Par ailleurs, que génère ta macro actuelle?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    As-tu essayé Ts...::mask et Ts::mask...
    Oui, dans les deux cas le compilateur me dit "Pack expansion does not contain any unexpanded parameter packs"

    Par ailleurs, que génère ta macro actuelle ?
    Eh bien par exemple,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    macro(Dog,Cow,Cat);
    std::cout << test.Dog << std::endl;
    std::cout << test.Cow << std::endl;
    std::cout << test.Cat << std::endl;
    std::cout << test.tab[0] << std::endl;
    std::cout << test.tab[1] << std::endl;
    std::cout << test.tab[2] << std::endl;
    Affiche ceci :

    0
    1
    2
    0
    1
    1

    Les trois premiers correspondent à l'enum, nikel, par contre les trois derniers, c'était pas franchement attendu comme résultat, moi jvoulais 2 4 1
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    C'est le code généré par la macro qui est intéressant.
    Tu peux l'obtenir avec certains réglages de compilation.
    Pour gcc, c'est -E, qui produit le code après le passage du préprocesseur (donc les macros) mais avant compilation.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 071
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 071
    Points : 12 116
    Points
    12 116
    Par défaut
    L'équivalent du -E de gcc pour Visual Studio, c'est /P.
    https://msdn.microsoft.com/en-us/lib...or=-2147217396

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    au passage, la macro devrait prendre le nom de la variable générée en argument. ici, "test" semble vraiment sortir du chapeau.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Hum.. Voui mais moi je suis sur XCode, avec clang comment qu'on fait ?

    Sinon j'ai trouvé une solution. Je passe par une fonction template :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename...Ts>
    std::vector<unsigned> createTab()
    {
        std::vector<unsigned> tmp = {Ts::mask...};
        return tmp;
    }
    Et j'encapsule mon enum dans une struct. Allez savoir pourquoi, si je ne le fais pas, ça marche pas. Sans doute parce qu'une fois que j'ai utilisé Ts dans une enum, le compilo considère que Ts ne peuvent être que des membres de l'enum, du coup je peux plus utiliser Ts pour autre chose.. Ça donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #define macro(Ts...)                \
    struct A                            \
    {                                   \
        struct { enum { Ts }; } index;  \
        std::vector<unsigned> tab;      \
        A() { tab = createTab<Ts>(); }  \
    } test;
    C'est pas très très propre mais ça marche

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    macro(Dog,Cow,Cat);
    std::cout << test.index.Dog << std::endl;
    std::cout << test.index.Cow << std::endl;
    std::cout << test.index.Cat << std::endl;
    std::cout << test.tab[0] << std::endl;
    std::cout << test.tab[1] << std::endl;
    std::cout << test.tab[2] << std::endl;
    print :
    0
    1
    2
    2
    4
    1

    Du coup, pour générer le code de la macro, ça se passe comment ? (Je suis quand même preneur d'une solution plus propre)
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    d'après cette documentation, c'est -E aussi
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<class... Ts> 
    struct array_mask {
      static unsigned constexpr tab[] = {Ts::mask...};
    };
    template<class... Ts>
    constexpr unsigned array_mask<Ts...>::tab[sizeof...(Ts)];
     
    #define macro(...)               \
    struct : array_mask<__VA_ARGS__> \
    {                                \
      enum { __VA_ARGS__, count };   \
    }

  10. #10
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<class... Ts> 
    struct array_mask {
      static unsigned constexpr tab[] = {Ts::mask...};
    };
    template<class... Ts>
    constexpr unsigned array_mask<Ts...>::tab[sizeof...(Ts)];
     
    #define macro(...)               \
    struct : array_mask<__VA_ARGS__> \
    {                                \
      enum { __VA_ARGS__, count };   \
    }
    Vous m'épaterez toujours, les gars.. C'est propre, clair, et efficace. Fallait juste ça, en fait. Chapeau, Merci !
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Mais une macro est-elle nécessaire ou utile pour obtenir ce résultat?
    une template ne suffirait-elle pas?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Cela oblige de dupliquer l'information. Une fois pour l'enum, une autre fois dans la template.
    Après, il est possible de faire en sorte que le type soit une clef convertible en un identifiant. Ceci permet également de générer la valeur mask automatiquement. Mais au prix d'un code plus verbeux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main(){
      type_enum_mask<Dog, Cow, Cat>
        animals{};
     
      std::cout
        << animals.index<Dog>() << '\n'
        << animals.index<Cow>() << '\n'
        << animals.index<Cat>() << '\n'
        << animals.masks[0] << '\n'
        << animals.masks[1] << '\n'
        << animals.masks[2] << '\n'
      ;
    }
    (Si vous le voulez, je peux faire le code pour arriver au résultat).

  13. #13
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    Cela oblige de dupliquer l'information. Une fois pour l'enum, une autre fois dans la template.
    Après, il est possible de faire en sorte que le type soit une clef convertible en un identifiant. Ceci permet également de générer la valeur mask automatiquement. Mais au prix d'un code plus verbeux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main(){
      type_enum_mask<Dog, Cow, Cat>
        animals{};
     
      std::cout
        << animals.index<Dog>() << '\n'
        << animals.index<Cow>() << '\n'
        << animals.index<Cat>() << '\n'
        << animals.masks[0] << '\n'
        << animals.masks[1] << '\n'
        << animals.masks[2] << '\n'
      ;
    }
    (Si vous le voulez, je peux faire le code pour arriver au résultat).
    Mais une macro est-elle nécessaire ou utile pour obtenir ce résultat?
    une template ne suffirait-elle pas?
    Moi, je veux bien voir, par curiosité Même si, pour être tout à fait franc, je me demande toujours pourquoi il faudrait chercher à faire compliqué quand on peut faire simple. Je veux dire, avec une macro, le code est torché en 5 lignes
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  14. #14
    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 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par leternel Voir le message
    Mais une macro est-elle nécessaire ou utile pour obtenir ce résultat?
    une template ne suffirait-elle pas?
    Je ne vois aucun moyen de générer un enum simplement avec un template seul.
    Il s'agit bien de le générer => macro
    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.

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

Discussions similaires

  1. macro qui crée une macro est ce possible
    Par redstoff dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 15/02/2011, 11h49
  2. Macro qui crée une macro
    Par ankoubzh dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 01/05/2009, 19h44
  3. problème : une macro qui crée un tableau
    Par watashi wa dans le forum Mise en forme
    Réponses: 1
    Dernier message: 22/04/2008, 09h22
  4. macro qui crée une macro, est ce possible ?
    Par Djohn dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 11/07/2007, 09h43
  5. Macro qui crée et renomme un controle
    Par k-eisti dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 04/06/2007, 17h17

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