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 :

Récupérer le parent namespace par template


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Récupérer le parent namespace par template
    Hello,

    un exemple qui marche:
    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
     
    #include <iostream>
    namespace A1{
    	namespace A2{
    		class Voiture{
    			public:
    			std::string toString(){return "A-Voiture";}		
    		};
    		class Accident{
    		public:
    			int getFee()const{return 0;}
    		};
    		//...		
    		class Definition{
    			public:
    			typedef A1::A2::Voiture MyVoiture;
    			typedef A1::A2::Accident MyAccident;
    		};
    	}
    }
    namespace B1{
    	namespace B2{
    		class Voiture{
    		public:
    			std::string toString(){return "B-voiture";}
    		};
    		class Accident{	
    		public:
    			int getFee()const{return 2;}
    		};
    		class Definition{
    			public:
    			typedef B1::B2::Voiture MyVoiture;
    			typedef B1::B2::Accident MyAccident;
    		};
    	}
    }
     
    template<typename Def>
    void registerCar(const typename Def::MyAccident& iAccident){
    	typename Def::MyVoiture aVoiture;
    	std::cout<<aVoiture.toString()<<":"<<iAccident.getFee()<<std::endl;
    }
    int main(){
     
    	A1::A2::Definition::MyAccident accidentA;	
    	registerCar<A1::A2::Definition>(accidentA);
    	B1::B2::Definition::MyAccident accidentB;
    	registerCar<B1::B2::Definition>(accidentB);
    /*
    Affiche:
    A-Voiture:0
    B-voiture:2
    */
     
      return 0;
    }
    L'arborescence des classes est imposée.
    Mon bras de levier c'est la méthode registerCar, qui prend un accident.
    Mon but c'est de trouver la voiture dans le même namespace que l'accident qui lui est passé en paramètre.

    J'aimerais ne pas avoir besoin de préciser registerCar<Type> mais simplement faire un appel registerCar(accidentA); étant donné que accidentA contient le type A1::A2::... j'aimerais pouvoir me servir de accidentA pour pouvoir utiliser A1::A2::MyVoiture

    Y a-t-il un moyen?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T, typename U>
    void registerCar(const typename T::U& iAccident){
    	typename T::MyVoiture aVoiture;
    	std::cout<<aVoiture.toString()<<":"<<iAccident.getFee()<<std::endl;
    }
    ne marche pas
    src/main.cpp:46:23: erreur: no matching function for call to ‘registerCar(A1::A2::Definition::MyAccident&)’
    src/main.cpp:46:23: note: candidate is:
    src/main.cpp:39:6: note: template<class T, class U> void registerCar(const typename T::U&)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>
    void registerCar(const typename T::MyAccident& iAccident){
    	typename T::MyVoiture aVoiture;
    	std::cout<<aVoiture.toString()<<":"<<iAccident.getFee()<<std::endl;
    }
    non plus
    src/main.cpp: In function ‘int main()’:
    src/main.cpp:46:23: erreur: no matching function for call to ‘registerCar(A1::A2::Definition::MyAccident&)’
    src/main.cpp:46:23: note: candidate is:
    src/main.cpp:39:6: note: template<class T> void registerCar(const typename T::MyAccident&)
    Merci !

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,

    Pourquoi ne pas, simplement, donner un typedef sur A1::A2::voiture, A1::A2::accident et A1::A2::definition dans toutes tes classes

    Une déclaration anticipée suffit parfaitement
    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
     
     
    namespace A1{
    namespace A2{
        class Accident;
        class Definition;
        class Voiture{
            public:
                typedef ::A1::A2::Accident accident_type;
                typedef ::A1::A2::Definition definition_type;
                // Hé oui, on peut parfaitement définir un typedef sur le type
                //que l'on est justement occupé à définir :D
                typedef ::A1::A2::Voiture voiture_type;
                void print() const{
                    std::cout<<"A1::A2::Voiture"<<std::endl;
                }
        };
        class Accident{
            public:
                typedef ::A1::A2::Accident accident_type;
                typedef ::A1::A2::Definition definition_type;
                typedef ::A1::A2::Voiture voiture_type;
        };
     
        class Definition{
            public:
                typedef ::A1::A2::Accident accident_type;
                typedef ::A1::A2::Definition definition_type;
                typedef ::A1::A2::Voiture voiture_type;
        };
    }
    }
    namespace B1{
    namespace B2{
        class Accident;
        class Definition;
        class Voiture{
            public:
                typedef ::B1::B2::Accident accident_type;
                typedef ::B1::B2::Definition definition_type;
                typedef ::B1::B2::Voiture voiture_type;
                void print() const{
                    std::cout<<"B1::B2::Voiture"<<std::endl;
                }
        };
        class Accident{
            public:
                typedef ::B1::B2::Accident accident_type;
                typedef ::B1::B2::Definition definition_type;
                typedef ::B1::B2::Voiture voiture_type;
        };
     
        class Definition{
            public:
                typedef ::B1::B2::Accident accident_type;
                typedef ::B1::B2::Definition definition_type;
                typedef ::B1::B2::Voiture voiture_type;
        };
    }
    }
    Même si on préféreras l'approche de C++11 qui tend à rendre l'usage de typedef obsolète:
    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
     
    namespace A1{
    namespace A2{
        class Accident;
        class Definition;
        class Voiture{
            public:
                using accident_type = ::A1::A2::Accident;
                using definition_type =  ::A1::A2::Definition;
                using voiture_type = ::A1::A2::Voiture;
                void print() const{
                    std::cout<<"A1::A2::Voiture"<<std::endl;
                }
        };
        class Accident{
            public:
                using accident_type = ::A1::A2::Accident;
                using definition_type =  ::A1::A2::Definition;
                using voiture_type = ::A1::A2::Voiture;
        };
     
        class Definition{
            public:
                using accident_type = ::A1::A2::Accident;
                using definition_type =  ::A1::A2::Definition;
                using voiture_type = ::A1::A2::Voiture;
        };
    }
    }
    namespace B1{
    namespace B2{
        class Accident;
        class Definition;
        class Voiture{
            public:
                using accident_type = ::B1::B2::Accident;
                using definition_type =  ::B1::B2::Definition;
                using voiture_type = ::B1::B2::Voiture;
                void print() const{
                    std::cout<<"B1::B2::Voiture"<<std::endl;
                }
        };
        class Accident{
            public:
                using accident_type = ::B1::B2::Accident;
                using definition_type =  ::B1::B2::Definition;
                using voiture_type = ::B1::B2::Voiture;
        };
     
        class Definition{
            public:
                using accident_type = ::B1::B2::Accident;
                using definition_type =  ::B1::B2::Definition;
                using voiture_type = ::B1::B2::Voiture;
        };
    }
    }
    A partir de là, tu peux récupérer le type de n'importe quoi au départ de n'importe où :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template <typename T>
    void registerData(T const & t){
        using voiture_t = typename T::voiture_type;
        voiture_t voiture;
        voiture.print();
    }
     
    int main(){
        A1::A2::Definition dA1A2;
        B1::B2::Definition dB1B2;
        registerData(dA1A2);
        registerData(dB1B2);
       return 0;
    }
    Par contre, je serais bien curieux de savoir la logique qui t'a poussé à avoir deux espace de noms totalement différents dans lesquels on trouve un espace de noms imbriqué qui définis à chaque fois les mêmes structures.

    J'ai très certainement loupé quelque chose, mais tu ne crois pas que tu dupliques peut être un peu beaucoup ton code en agissant de la sorte
    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

  3. #3
    Invité
    Invité(e)
    Par défaut
    En fait au taff, une certaine équipe est reponsable de A1::A2, une autre de B1::B2 et proposent une interface homogène.

    Néanmoins, je ne peux/veux pas modifier ces interfaces.
    Concernant le fait de passer une instance de Definition, ca ne m'intéresse pas puisque l'idée c'est que je passe une instance d'accident (j'ai besoin de me servir de l'accident), et passer l'instance de Definition revient à simplement passer par un template comme dans mon premier exemple!

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par galerien69 Voir le message
    En fait au taff, une certaine équipe est reponsable de A1::A2, une autre de B1::B2 et proposent une interface homogène.
    Et, dis moi, vous n'avez vraiment jamais eu l'idée de vous installer autour d'une table, avec un bon café (tant qu'à faire) et de réfléchir à la possibilité de regrouper ces deux espaces de noms en un seul (tools, par exemple), qui permettrait de n'avoir qu'une définition commune

    Cela risque de compliquer la procédure pour apporter des changements, je te l'accorde, mais si l'on y regarde de plus près, on se rend compte que comme ce sont des données métier, elles ne risquent malgré tout pas d'évoluer tous les trois jours
    Néanmoins, je ne peux/veux pas modifier ces interfaces.
    Nous ne partons pas sur des modifications importantes : il s'agirait juste de rajouter le ou les quelques typedef manquant(s)
    Concernant le fait de passer une instance de Definition, ca ne m'intéresse pas puisque l'idée c'est que je passe une instance d'accident (j'ai besoin de me servir de l'accident), et passer l'instance de Definition revient à simplement passer par un template comme dans mon premier exemple!
    Apparemment, j'aurais du prendre une des deux autres classes pour te faire comprendre

    Ici, j'ai utilisé la classe définition pour l'exemple, mais j'aurais très bien pu écrire un 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
    13
    14
    template <typename T>
    void registerVehicle(T const & t){
        using accident_type = typename T::accident_type;
        accident_t accident;
        accident.someAccidentBehaviour();
    }
     
    int main(){
        A1::A2::Voiture vA1A2;
        B1::B2::Definition vB1B2;
        registerVehicle(vA1A2);
        registerVehicle(vB1B2);
       return 0;
    }
    Cela serait revenu au même

    Ce qui importe, c'est que chaque type dispose d'un alias de type "standardisé" (comprends : qui porte à chaque fois le même nom dans tous les espaces de noms et dans toutes les classes) permettant d'identifier les autres types :
    • vehicle_type correspond, dans toutes les classes de tous les espaces de noms, au type de voiture
    • accident_type correspond, dans toutes les classes de tous les espaces de noms, au type d'accident et
    • description_type correspond, dans toutes les classes de tous les espaces de noms, au type de description.
    Cela ne coute strictement rien à l'exécution, simplement, cela te facilite la tâche lorsqu'il faut commencer à récupérer l'un ou l'autre type : tu sais que chaque type sera systématiquement identifiable par un type bien déterminé.

    Cela te permet, en quelque sorte, de rendre ton interface homogène et indépendante de l'endroit d'où viennent les données
    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

  5. #5
    Invité
    Invité(e)
    Par défaut
    Apparemment, j'aurais du prendre une des deux autres classes pour te faire comprendre
    oui je me suis arrêté sur le fait que t'avais du mal lire le premier poste alors que tu proposais de rajouter les typedefs dans Voiture ou Accident.. la fatigue!

    J'aimerais vraiment savoir si on peut s'en sortir sans modifier ces interfaces.

    Pour ce qui est de discuter de modifier les interfaces des classes, je t'avouerai franchement que ca prend du temps, faut trouver les gens, au bon moment, et j'ai d'autres chats à fouetter (comme prendre un café par exemple!)
    (on parle pas de deux classes, mais plus genre la cinquantaine sinon plus, avec une bonne vingtaine d'équipes responsable de leur classes)

    C'est plus pour la curiosité

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par galerien69 Voir le message
    oui je me suis arrêté sur le fait que t'avais du mal lire le premier poste alors que tu proposais de rajouter les typedefs dans Voiture ou Accident.. la fatigue!

    J'aimerais vraiment savoir si on peut s'en sortir sans modifier ces interfaces.
    A mon sens, non:

    Il faut comprendre que les espaces de noms ne sont pas des "méga structures" qui engloberaient l'ensemble des types et fonctions qu'ils contiennent.

    Tu devrais plutôt les voir comme des préfixes placés devant les différents types afin d'assurer une unicité référencielle (tout comme openGl préfixe généralement ses fonctions et ses types de glXXX).

    Nous pourrions faire le parallèle avec les deux derniers chiffres d'une plaque (ancienne) française ou avec le préfixe utilisé par les différents opérateurs télécom qui permettent de assurer une identification stricte

    Pour autant que je sache (car je peux toujours me tromper, même si je suis relativement sûr de mon coup), les espaces de noms n'interviennent que dans le processus qui permet d'éviter toute ambigüité lors de la recherche de concordances ("mangling").
    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
    Invité
    Invité(e)
    Par défaut
    oui ca se tient.
    Voilà un lien que je viens de trouver qui dit à peu près la même chose ici

    merci

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

Discussions similaires

  1. Récupérer la table affichée par FREQ
    Par pedouille dans le forum SAS Base
    Réponses: 2
    Dernier message: 29/05/2007, 15h30
  2. Réponses: 2
    Dernier message: 04/10/2005, 11h12
  3. [Système] récupérer l'HTML généré par ma page PHP
    Par saint-pere dans le forum Langage
    Réponses: 2
    Dernier message: 27/09/2005, 10h19
  4. Réponses: 2
    Dernier message: 10/05/2005, 19h33
  5. récupérer l'événement "fermeture par la croix" de
    Par hamurielle dans le forum Windows Forms
    Réponses: 4
    Dernier message: 08/04/2005, 10h35

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