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 :

Problème avec deux namespace


Sujet :

C++

  1. #1
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut Problème avec deux namespace
    Salut tout le monde Aujourd'hui met arrivé un problème que je n'avais jamais eu. J'ai deux namespace où les deux namespace sont "lier" ( le namespace a à besoin du b et inversement ).

    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
     
     
    namespace a
    {
        enum A{e, l, e, m);
     
       void foo(b::B b);
    }
     
    namespace b
    {
        enum B{t, r, u, c);
     
        void foo(a::A a);
    }
    Comment faire dans ce cas ?

    Merci

  2. #2
    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
    Hello

    Il faut simplement jouer sur l'ordre des déclarations. Il te faut des headers dédiés aux enums puis des headers dédiés aux fonctions, séparés.

    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
    namespace a {
    enum A{e, l, m};
    }
     
    namespace b {
    enum B{t, r, u, c};
    }
     
    namespace a {
    void foo(b::B b);
    }
     
    namespace b {
    void foo(a::A a);
    }

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    Il est aussi possible de faire une "forward declaration" d'une énum.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    namespace b {
      enum B;
    }
     
    namespace A{
      enum A{...};
      void foo(b::B);
    }
     
    namespace B{
      enum a{...};
      void foo(a::A);
    }

  4. #4
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut
    Merci pour vos réponses , concernant la "forward declaration" d'une énum, es-que c'est propre de faire comme ça ? Dans tout les cas ça me paraît un peu plus confus de faire comme ça, donc je vais m'en tenir à la première méthode

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    L'avantage d'une forward declaration (ou déclaration anticipée, en français), c'est que cela peut aider à retirer des includes dans les en-têtes, et donc potentiellement, à réduire les temps de compilations.

  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
    Salut,

    Bien que les solutions t'aient été données, je crois que, à la base, tu as un sérieux problème de conception!

    D'une manière ou d'une autre, un espace de noms peut être assimilé à un "module", et si (je ne fais que changer de terme là) le module A dépend du module B et que module B dépend du module A, la question qu'il est largement temps de se poser est : a-t-on réellement bien fait de séparer le contenu des deux modules

    D'ailleurs, c'est bien simple : dés que l'on se trouve face à un problème de dépendance cyclique, (qu'elle survienne entre deux classes, entre deux espaces de noms ou entre deux modules) il serait bon d'envisager de revoir la conception, ne serait-ce que pour pouvoir justifier (si possible, autrement que par un "parce que je n'ai pas le choix" ) cette "cyclicité".

    Qu'il y ait un module qui dépende d'un autre, ca peut sembler logique, mais que la dépendance soit cyclique, ca ne présage pas grand chose de bon

    @ternel : Attention! j'ai un peu la flegme de vérifier, mais, sauf erreur, il n'y a que les énumérations fortes (enum class, apparues avec C++11) qui supportent la déclaration anticipée.

    Maintenant, j'ai peut être loupé quelque chose du fait que les énumérations sont dans des espaces de noms différents, mais j'en doute très fort

    Mais bon, le plus simple (pour ce qui concerne les énumérations, en tout cas) est peut-être "tout simplement" de les mettre dans des fichiers d'en-tête qui ne contiendraient qu'elles, histoire que l'inclusion d'un fichier ne provoque pas l'ajout de la définition d'un tas de classes (qui -- elles -- peuvent parfaitement se contenter d'une déclaration anticipée )
    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
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    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 202
    Par défaut
    En effet, il y a un léger détail, pour les unscoped enumerations, c'est autorisé depuis C++11, mais il faut préciser le type sous-jacent.
    Le type produit est complet, mais les énumérateurs sont inconnus (opaque enumeration declaration).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    enum bidule : unsigned char;

  8. #8
    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
    Ah... J'avais donc tort (car coder en respectant une norme antérieur à C++11 est une véritable hérésie, à moins de maintenir un vieux projet ), mais pas trop, dans le sens où il manquait effectivement un détail important dans ton exemple

    En plus, cela n'invalide absolument pas le reste de mon intervention
    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

  9. #9
    Membre très actif
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Par défaut
    J'ai finalement suivi ton conseil Koala, j'ai créé un namespace contenant toutes les énumérations "importantes" c'est bien plus propre et plus simple à utiliser. Au début je ne voulais pas faire comme ça car ces enums n'avaient rien en commun, j'avais des enums concernant des type d'erreurs et d'autres choses dans le même thème tandis que les autres enum ce portées plus sur les événements, des actions, des états, etc..

  10. #10
    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 Disixlis Voir le message
    J'ai finalement suivi ton conseil Koala, j'ai créé un namespace contenant toutes les énumérations "importantes" c'est bien plus propre et plus simple à utiliser. Au début je ne voulais pas faire comme ça car ces enums n'avaient rien en commun, j'avais des enums concernant des type d'erreurs et d'autres choses dans le même thème tandis que les autres enum ce portées plus sur les événements, des actions, des états, etc..
    Hummm.... Déjà, le fait de travailler avec des énumérations pour obtenir une sorte de RTTI (Run Time Type Information ou "information sur le type à l'exécution"), c'est ... Moyen moyen du point de vue de la conception.

    Ne serait-ce que parce que je parie que ca occasionne une multiplication de code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    switch(some_var){
        case value_1 :
            dynamic_cast<Type1 * >(truc)->foo(/* ... */);
            break;
     
        case value_2 :
            dynamic_cast<Type2 * >(truc)->bar(/* ... */);
            break;
        case value_3 :
            dynamic_cast<Type3 * >(truc)->doIt(/* ... */);
            break;
    /*....*/
    Bien sur, il peut y avoir quelques variations sur ce thême : utilisation de référence au lieu de pointeurs, utilisation de static_cast (voir d'un cast "perso" effectuant un dynamic_cast en débug et un static_cast en release)au lieu du dynamic_cast, mais, le problème avec cette approche, c'est que tu dis totalement adieu au O de SOLID, qui, comme tout le monde le sait, est là pour représenter l'OCP (Open / Close Principe ou "principe d'un code "ouvert (aux évolutions mais) fermé (aux modifications)").

    En effet, cela t'oblige systématiquement à modifier tous les endroits où ce genre de code apparait dés que tu souhaites ajouter un type supplémentaire à ta hiérarchie de classes; au risque de "justement" oublier le seul endroit du code où la non modification occasionnera une catastrophe

    Pour gérer ce genre de problème, rien ne vaut l'idiome du "double dispatch", dont l'exemple le plus connu est donné par le patron "visiteur".

    Et puis, si ces énumérations n'ont vraiment rien à voir entre elles, les endroits du code où tu les utilise devraient théoriquement être tout aussi distincts : les énumérations qui se trouvent dans l'espace de noms A ne devraient être utilisées... que par les classes qui se trouvent dans l'espace de noms A, et les énumérations se trouvant dans l'espace de noms B ne devraient être utilisées... que par les classes se trouvant dans l'espace de noms B.

    Et comme le fait d'utiliser une énumération est -- typiquement -- assimilé à un "détail d'implémentation", si même tu venais à trouver une bonne raison pour avoir une dépendance circulaire entre une (ou plusieurs) classe(s) de l'espace de noms A et une (ou plusieurs) classe(s) de l'espace de noms B (ce qui ne devrait jamais arriver, soit dit en passant), tu violerais de toutes façons à la loi de Déméter en faisant en sorte que les classes de l'espace de noms A aient besoin des énumérations de l'espace de noms B et réciproquement.

    Bref, tes explications me confortent sur le fait que... tu as un très gros problème de conception et de modularisation à la base de tout, et que tu aurais vraiment largement intérêt à le corriger tant qu'il en est encore temps
    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. [MySQL] problème avec deux requetes dans un même script
    Par leclone dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 09/02/2007, 10h28
  2. [CSS] Problème avec deux div côte-à-côte
    Par Etanne dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 31/07/2006, 13h58
  3. [DOM] Problème avec les namespaces
    Par clincks dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 26/06/2006, 20h40
  4. Problème avec deux interfaces
    Par ikeaboy dans le forum Langage
    Réponses: 2
    Dernier message: 28/05/2006, 14h56
  5. Réponses: 22
    Dernier message: 29/01/2005, 11h29

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