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 :

Template et Surcharge


Sujet :

Langage C++

  1. #1
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut Template et Surcharge
    Bonsoir,

    Voici d'abord le code (simplifié et regroupé en un seul fichier) :
    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    #include<algorithm>
    #include<cstdlib>
    #include<iostream>
    #include<utility>
    #include<vector>
     
    //Déclaration ancitipé
    template<class DrawerData>
    struct Drawer;
     
    //Première fonction template générique
    template<class T, class DrawerData>
    void accept(T& t, Drawer<DrawerData>& d)
    { t.accept(d); }
     
    //Doit être utilisé en tant que classe de base
    template<class Entity, class C>
    struct AcceptPolicy
    {
    	C& c;
     
    	AcceptPolicy(C& c) : c(c) {}
    	//C'est une classe de politique qui offre ce comportement
    	template<class DrawerData>
    	void accept(Drawer<DrawerData>& d)
    	{
    		std::for_each(c.begin(),c.end(),
    			[&d](typename C::value_type& t)
    		{ 
    			::accept(t,d); 
    			//Permettre un point de variation en restant générique
    		} );
    	}
    };
     
    /*Pas de changement possible avant*/
    //Une utilisation de cette classe de politique
    struct MyEntity : AcceptPolicy<MyEntity,std::vector<std::pair<MyEntity*,int> > >
    {
    	typedef std::pair<MyEntity*,int> PairType;
     
    	std::vector<PairType> v;
     
    	MyEntity() : AcceptPolicy(v) 
    	{ v.push_back(PairType(new MyEntity(0),0)); }
    	MyEntity(int) : AcceptPolicy(v) {}
    };
     
    //Une surcharge d'accept "meilleur choix" que la version générique
    template<class DrawerData>
    void accept(MyEntity::PairType& t, Drawer<DrawerData>& d)
    { 
    	std::cout << 0; 
    	t.first->accept(d);
    	std::cout << 1; 
    }
     
    //Une classe pour tester
    struct MyDrawerData {};
     
    //Une spécialisation de la classe template déclaré
    template<>
    struct Drawer<MyDrawerData> { };
     
    int main()
    {
    	//De quoi testet
    	Drawer<MyDrawerData> d; MyEntity e;
    	e.accept(d);
    }
    L'objectif du code est de fournir une classe de politique basé sur le CRTP (et un autre TP), offrant un comportement avec un point de variation.

    L'idée que j'ai eu est d'appeler la fonction ::accept(t,o); dans la fonction membre accept(o) sur l'ensemble des éléments d'un conteneur connu par la classe de politique grâce au constructeur de celui-ci.

    La version générique de la fonction ::accept(t,o); se contente juste d'appeler t->accept(o); mais si le type des valeurs du conteneur sont plus complexe (comme dans ce code : une pair) il faut le redéfinir, pour ca je propose une surcharge (template pour conserver la généricité sur le second paramètre) de ::accept dans ce cas là.

    Ce code fonctionne comme prévu sous VC++ mais pas sous gcc :
    In function 'void accept(T&, Drawer<DrawerData>&) [with T = std::pair<MyEntity*, int>, DrawerData = MyDrawerData]':
    30:4: instantiated from 'AcceptPolicy<Entity, C>::accept(Drawer<DrawerData>&) [with DrawerData = MyDrawerData, Entity = MyEntity, C = std::vector<std::pair<MyEntity*, int> >]::<lambda(std::vector<std::pair<MyEntity*, int> >::value_type&)>'
    28:6: instantiated from 'AcceptPolicy<Entity, C>::accept(Drawer<DrawerData>&) [with DrawerData = MyDrawerData, Entity = MyEntity, C = std::vector<std::pair<MyEntity*, int> >]::<lambda(std::vector<std::pair<MyEntity*, int> >::value_type&)>'
    27:3: instantiated from 'void AcceptPolicy<Entity, C>::accept(Drawer<DrawerData>&) [with DrawerData = MyDrawerData, Entity = MyEntity, C = std::vector<std::pair<MyEntity*, int> >]'
    69:12: instantiated from here
    14:3: error: 'struct std::pair<MyEntity*, int>' has no member named 'accept'
    Je pense que l'erreur vient des points d'instanciation des templates à des endroits différents pour VC++ et GCC ainsi dans un cas pas de problème et dans l'autre les surcharges ne sont pas connues lors de l'utilisation : d'où l'erreur (NB: Je suis loin d'être convaincu de mon analyse ...)

    Ma question est donc comment faire ce que je veut (mettre en place un point de variation dans une fonction générique), sachant que ce qui est au dessus de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /*Pas de changement possible avant*/
    Doit être générique, dans mon architecture (plus complète), le reste est amener à évoluer de manière significative : d'autre classes similaires à MyEntity, des possibilités d'utiliser d'autre classes que MyDrawerData (et donc des spécialisations qui en découle). Et que l'ordre de déclaration/définition des éléments est difficilement modifiable (j'ai tout regroupe en un seul fichier, mais il s'agit au départ d'include, ca impose "plus ou moins" l'ordre dans mon cas).

    Merci d'avance pour les éventuelles idées/suggestions.

  2. #2
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Est-ce ton ::accept(t,d), etant full-qualifié, n'empeche pas l'ADL et donc la recherche du accept défini a posteriori ?

  3. #3
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Merci.

    En effet (dans mon code d'origine il y a un namespace devant les :: ), j'ai donc rajouté un using ::accept juste avant l'appel ::accept(t,d) et ca marche.

    Dans mes premiers test sous VC++ je ne qualifiais pas le nom mais dans ce cas VC++ ne le trouvait pas (même sans aucun namespace nul part), c'est normal où il aurait du le trouver ?

    Au final c'est VC++ qui est trop laxiste et applique quand même l'ADL alors qu'il ne devrait pas ?

    Encore merci.

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

Discussions similaires

  1. Template et surcharge d'operateur affectation
    Par themadmax dans le forum C++/CLI
    Réponses: 3
    Dernier message: 04/04/2012, 19h07
  2. template class & surcharge de méthode
    Par Gébix dans le forum C++
    Réponses: 2
    Dernier message: 27/12/2011, 00h38
  3. Template et surcharge d'opérateur
    Par AF_2.8 dans le forum C++
    Réponses: 6
    Dernier message: 12/07/2011, 15h11
  4. souci classe template et surcharge operateur
    Par loicounet dans le forum Langage
    Réponses: 8
    Dernier message: 28/04/2008, 15h01
  5. friend surcharge classe template
    Par fridollin dans le forum Langage
    Réponses: 4
    Dernier message: 15/11/2005, 21h37

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