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

Langage C++ Discussion :

typedef d'une enum


Sujet :

Langage C++

  1. #1
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut typedef d'une enum
    Bonjour,

    J'aimerais « dupliquer » une enum.
    Naïvement, j'ai écrit ce code, qui ne fonctionne pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    enum uneEnum {A, B, C};
     
    class maClasse
    {
     
      public:
        typedef uneEnum monEnum;
     
    };
    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
    class uneClasse
    {
     
      public:
        enum uneEnum {A, B, C};
     
    };
     
    class maClasse
    {
     
      public:
        typedef uneClasse::uneEnum monEnum;
     
    };
    En fait, le type maClasse::monEnum semble bien exister, mais si j'essaie quelque chose du genre : "maClasse::A", j'ai un message d'erreur :
    « A » n'est pas membre de « maClasse ».
    Quelqu'un aurait des suggestions ?

    Ah oui, une dernière chose.
    Je n'ai pas de contrôle sur les fichiers dans lesquels sont définies les enums.
    [edit]Quant aux enums, elles sont générées automatiquement, et donc leur contenu n'est pas fixe (même s'il est facilement déterminable).[/edit]
    J'aimerais faire une sorte de « façade », qui soit utilisable que l'enum soit déclarée dans l'espace de nom global ou à l'intérieur d'une autre classe.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    As-tu essayé

    ?

  3. #3
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Maintenant, oui :
    « maClasse::monEnum » n'est pas une classe ou un espace de nom

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Mais comment l'utilises-tu ?

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    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
    class uneClasse
    {
     
      public:
        enum uneEnum {A, B, C};
     
    };
     enum
     {
         A,B,C
     };
    class maClasse
    {
     
      public:
        enum monEnum
        {
           A = uneClasse::A
          ,B = uneClasse::B
          ,C = uneClasse::C
        };
        enum
        {
            A2 = ::A // ::A pour ne pas faire une redéfinition du A juste avant de monEnum
            ,B2 = ::B
            ,C2 = ::C
        };
     
    };
    pas mieux

  6. #6
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    @3DArchi: Je te remercie, mais j'y avais déjà pensé, et j'aimerais autant éviter de redéfinir les enums.
    Vu qu'elles sont générées automatiquement (par un programme externe, bison en l'occurrence), je ne peux pas le faire si je veux faire une classe générique.
    C'est sûr que pour un projet donnée, je pourrais me le permettre, mais bon...

    Citation Envoyé par oodini Voir le message
    Mais comment l'utilises-tu ?
    Hum... Je ne suis pas sûr de comprendre ta question...
    Que veux-tu dire exactement par là ?


    Vu la tournure que prennent les choses, je sens que vais me tourner vers une macro qui se chargera de donner la syntaxe appropriée.
    Oui, je sais, ce n'est pas top...

  7. #7
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Selon le compilateur que tu utilises, il pourrait être intéressant d'utiliser des classes d'énumération (cf. http://blog.emmanueldeloget.com/inde...d-enumerations).

    Si ton compilateur ne supporte pas cette nouvelle fonctionnalité, j'utiliserais quelque chose de nettement plus complexe, mais oh combien plus sur que des enums :

    Code mon_enum.h : 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
     
    class mon_enum
    {
    public:
      static const mon_enum v1;
      static const mon_enum v2;
      static const mon_enum v4;
    private:
      enum real_enum 
      { real_enum_v1, real_enum_v2, real_enum_v3 };
      mon_enum(const real_enum& e) : m_value(e) { }
      real_enum m_value;
    public:
      mon_enum(const mon_enum& other) : m_value(other.m_value) { }
      mon_enum() : m_value(real_enum_v1) { }
     
      bool operator==(const mon_enum& other) const
      { return m_value == other.m_value; }
     
      bool operator!=(const mon_enum& other) const
      { return m_value != other.m_value; }
     
      int get() const // utilisé pour les switch/case
      { return static_cast<int>(m_value); }
     
      mon_enum& operator=(const mon_enum& other)
      { mon_enum(other).swap(*this); return *this; }
     
      void swap(mon_enum& other)
      { std::swap(m_value, other.m_value); }
    };

    Code mon_enum.cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include "mon_enum.h"
     
    const mon_enum mon_enum::v1(mon_enum::real_enum_v1);
    const mon_enum mon_enum::v2(mon_enum::real_enum_v2);
    const mon_enum mon_enum::v3(mon_enum::real_enum_v3);

    Et non, on ne peut pas templatiser. Ceci dit, les avantages offerts sont nombreux : pas de conversion implicite vers int, les symboles publics (v1, v2, ...) sont des instances statiques constantes et non pas des valeurs d'énumération, ce qui a un gros intérêt parce que deux énumérations du même namespace ne peuvent pas définir un énumérateur du même nom, et mon_enum est une classe - je peux donc lui faire faire des choses sympa, comme une méthode to_string(), une méthode is_v1_or_v2() dis comme ça, ça choque, mais si l'énumération représente un code d'erreur, on peut maintenant vérifier aisément si une erreur appartient à une classe d'erreur (par exemple : is_net_error()) ou non). Le prix à payer en terme de code est minimal - celà m'a pris presque 8 minutes pour écrire le code ci-dessus.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Mon chef de projet m'interdit d'utiliser les const static, et m'oblige à utiliser des enum...

  9. #9
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par oodini Voir le message
    Mon chef de projet m'interdit d'utiliser les const static, et m'oblige à utiliser des enum...
    Ton chef n'a pas compris ce qu'était const static dans ce contexte, sinon il verrais qu'il n'a strictement aucune espèce de raison de te l'interdire
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Il dit que les static const prennent de la place en mémoire (contrairement aux enums) et qu'ils posent problème en multithread...

  11. #11
    screetch
    Invité(e)
    Par défaut
    c'est vrai que les static const posent plein de problèmes en multithreads, c'est surtout la partie "const". Le fait qu'on peut jamais les changer depuis tous les threads, c'est un danger permanent.

  12. #12
    screetch
    Invité(e)
    Par défaut
    static const int:

    -rwxr-xr-x 1 yngwe yngwe 4805 Sep 28 13:15 sint.

    enum:
    -rwxr-xr-x 1 yngwe yngwe 4806 Sep 28 13:16 enum.

    les enum prennent un octet de plus...

  13. #13
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    @Emmanuel Deloget Merci pour ta réponse, je vais la garder dans un coin de ma tête pour la réutiliser plus tard.
    Malheureusement, dans le cas qui m'intéresse ce n'est pas applicable, et pour deux raisons.

    Déjà, le code que j'écris est fait pour être distribué.
    Je ne peux pas prévoir quels seront les compilateurs seront utilisés ni leurs capacités.
    De fait, je préfère me restreindre au C++ « standard » (si on peut l'appeler comme ça), ce qui devrait m'assurer une meilleure portabilité.
    C'est probablement un choix contestable, d'autant plus que certaines fonctionnalités du C++11 m'intéresseraient grandement (std::move et les pointeurs intelligents par exemple, même si je me débrouille au mieux pour implémenter un RAII correct), mais c'est un autre débat (peut-être même existe-t-il déjà un topic sur le sujet ?).
    Peut-être devrais-je faire une version C++ et une version C++11 « expérimentale »...

    Pour en revenir aux enums sont générées par bison (pour les tokens).
    Pour être précis, si on lui demande un parser C, il crée une enum dans l'espace de nom global ; si on lui demande un parser C++, il crée un enum à l'intérieur d'une struct, elle-même à l'intérieur d'une classe.
    Par exemple :
    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
    // parser C
     
    enum yytokentype {
        TOKEN1 = ...,
        TOKEN2 = ...,
        ...
    };
     
    ////////////////////////////////
     
    // parser C++
     
    namespace yy
    {
     
        class parser
        {
     
          public:
            struct token
            {
                enum yytokentype {
                    TOKEN1 = ...,
                    TOKEN2 = ...,
                    ...
                };
            };
            typedef token::yytokentype token_type;
     
            (...)
     
        };
     
    }
    Maintenant, la question est : « Pourquoi laisser la possibilité de générer un parser C dans un projet en C++ alors que le parser C++ fait très bien le boulot ? »
    Eh bien pour la même raison que précédemment.
    L'utilisateur final n'utilise peut-être pas bison, ou une version de bison qui ne peut pas générer de parser C++.
    Il ne reste plus qu'à espérer que le générateur de parser utilisé est suffisamment compatible avec bison pour que le fichier de grammaire et le code fonctionnent...
    Ou alors dois-je obliger les utilisateur à utiliser une version adéquate de bison ?

    Ce que j'aimerais, c'est une classe qui définit une énumération dans son propre espace de nom (peu importe son implémentation) correspondant à la liste des tokens générés par bison, que l'approche utilisée soit le C ou le C++.
    Comme le suggère 3DArchi, je pourrais la redéfinir complètement, vu que je peux connaître le contenu de l'enum (pour chaque parser, du moins).
    Mais je préférerais éviter.

    Et au-delà de mon cas particulier, je me demandais s'il était possible qu'une classe intègre dans son propre espace de nom une enum définie ailleurs, si on en peux/veux pas utiliser les classes d'énumération ou l'astuce que tu donnes.

    PS: Dans le cas présent, la conversion implicite vers int est nécessaire, voire indispensable.

  14. #14
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par screetch Voir le message
    c'est vrai que les static const posent plein de problèmes en multithreads, c'est surtout la partie "const". Le fait qu'on peut jamais les changer depuis tous les threads, c'est un danger permanent.
    Euh...
    C'est ironique, ou bien... ?

  15. #15
    screetch
    Invité(e)
    Par défaut
    oui

  16. #16
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par oodini Voir le message
    Il dit que les static const prennent de la place en mémoire (contrairement aux enums) et qu'ils posent problème en multithread...
    Vu que ce sont des constantes, ils ne peuvent pas poser de problème en MT.

    Et oui, les static const prennent de la place en mémoire, mais d'un autre coté, elles ont une adresse (ce qui peut être une propriété désirable dans certains cas). Ensuite, la place en mémoire prise est exactement le sizeof() du type * le nombre d'énumérateurs. Sur l'énumération donnée, on arrive royalement à 12 bytes, ce qui n'est pas vraiment excessif. Même si tu cibles des systèmes embarqué, à partir du moment où tu utilises du C++ tu abandonnes quand même une bonne partie de tes prétentions sur les contraintes de mémoire : il ne faut quand même pas exagérer. Quand bien même on mettrais une dizaine de valeurs et plusieurs dizaines d'énums, on arriverais joyeusement à 2K ? allez, soyons fous : 4K ? Même dans le monde embarqué actuel (ou on a régulièrement au moins 4 Mo de RAM, quand ce n'est pas 512), c'est quand même loin de poser un soucis. On ne parle même pas du monde des PC, ou on commence à voir germer ici et là des machines avec 8 Go ou 16 Go de RAM.

    Effectivement, les enums ne prennent pas de place en mémoire. En contrepartie, ils ne sont pas typesafe, posent des problèmes au moment de la compilation du fait qu'ils ne respectent pas leur portée de définition (avoir une valeur VIOLET dans l'enum color et dans l'enum flower est impossible) ce qui a, de tout temps, nécessité l'utilisation de préfixes sur les enums, se transforment implicitement en int, sont stockés dans des variables dont la taille est inconnue et non maitrisée, nécessitent des tas de tests ici et là pour vérifier que les valeurs ne sortent pas de la liste donnée, etc.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  17. #17
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Vu que ce sont des constantes, ils ne peuvent pas poser de problème en MT.

    Et oui, les static const prennent de la place en mémoire, mais d'un autre coté, elles ont une adresse (ce qui peut être une propriété désirable dans certains cas). Ensuite, la place en mémoire prise est exactement le sizeof() du type * le nombre d'énumérateurs. Sur l'énumération donnée, on arrive royalement à 12 bytes, ce qui n'est pas vraiment excessif. Même si tu cibles des systèmes embarqué, à partir du moment où tu utilises du C++ tu abandonnes quand même une bonne partie de tes prétentions sur les contraintes de mémoire : il ne faut quand même pas exagérer. Quand bien même on mettrais une dizaine de valeurs et plusieurs dizaines d'énums, on arriverais joyeusement à 2K ? allez, soyons fous : 4K ? Même dans le monde embarqué actuel (ou on a régulièrement au moins 4 Mo de RAM, quand ce n'est pas 512), c'est quand même loin de poser un soucis. On ne parle même pas du monde des PC, ou on commence à voir germer ici et là des machines avec 8 Go ou 16 Go de RAM.

    Effectivement, les enums ne prennent pas de place en mémoire. En contrepartie, ils ne sont pas typesafe, posent des problèmes au moment de la compilation du fait qu'ils ne respectent pas leur portée de définition (avoir une valeur VIOLET dans l'enum color et dans l'enum flower est impossible) ce qui a, de tout temps, nécessité l'utilisation de préfixes sur les enums, se transforment implicitement en int, sont stockés dans des variables dont la taille est inconnue et non maitrisée, nécessitent des tas de tests ici et là pour vérifier que les valeurs ne sortent pas de la liste donnée, etc.
    Ils ne prendront de la place que si on en utilise l'addresse; sinon le linker va éliminer les références inutiles et les 4 octets n'apparaîtront pas. Donc on parle bien d'une perte de 0 octets dans le cas ou on utilise des static const a la palce des enums (et pour une raison que j'ignore, on parle meme d'un gain de 1 octet sous linux, ce qui j'admets est negligeable)

  18. #18
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Vous prêchez auprès d'un convaincu (désespéré) !!!

    Citation Envoyé par screetch Voir le message
    Ils ne prendront de la place que si on en utilise l'addresse; sinon le linker va éliminer les références inutiles et les 4 octets n'apparaîtront pas. Donc on parle bien d'une perte de 0 octets dans le cas ou on utilise des static const a la palce des enums (et pour une raison que j'ignore, on parle meme d'un gain de 1 octet sous linux, ce qui j'admets est negligeable)
    Je lui ai déjà sorti cet argument, mais il dit que c'est une optimisation de compilateur qui n'est pas dans la norme...

  19. #19
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Bon, si je comprends bien, la « solution » serait soit de redéfinir l'énumération, soit de faire une macro qui appellera la bonne syntaxe... soit de réécrire bison...

    Pas génial tout ça...

    Quoiqu'il en soit, merci à tous.

    Tout cette discussion me fait penser que je me suis toujours demandé pourquoi Qt définissait son propre type d'enum...

  20. #20
    screetch
    Invité(e)
    Par défaut
    ah. OK. Une andouille. J'avais pas compris désolé

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. accès aux éléments d'une enum
    Par aymeric__ dans le forum C++
    Réponses: 6
    Dernier message: 17/08/2006, 21h17
  2. Affectation/récupération de valeurs dans une Enum ?
    Par elitost dans le forum Langage
    Réponses: 2
    Dernier message: 27/06/2006, 16h12
  3. Réponses: 4
    Dernier message: 25/02/2006, 13h30
  4. Réponses: 17
    Dernier message: 16/10/2005, 21h01
  5. Sortir un typedef d'une classe
    Par Theophil dans le forum C++Builder
    Réponses: 13
    Dernier message: 03/07/2002, 17h21

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