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 :

Templates, Nested class & friend functon


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mai 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2009
    Messages : 26
    Points : 18
    Points
    18
    Par défaut Templates, Nested class & friend functon
    Bonjour à tous,

    Je souhaite rendre un opérateur de flux (<<) ami d'une classe LinkedList et d'une sous classe LinkedList::LinkedNode.

    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
     
    template<typename T>
    class LinkedList
    {
          friend ostream& operator<<(ostream&, const LinkedList<T>&);
          template<typename T>
          class LinkedNode
          {
                 friend class LinkedList<T>;
                 friend ostream& operator<<(ostream&, const LinkedList<T>&);
              private:
                  T element;
                  LinkedNode<T>* next;
          }
     private:
          LinkedNode<T>* head;
          LinkedNode<T>* tail;
    }
    voici maintenant l'opérateur ami:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    template <typename T>
    ostream& operator<<(ostream& out, const LinkedList<T>& list)
    {
           LinkedList<T>::LinkedNode<T>* temp = list.head;
           // ce code ne fait rien, j'essaye juste d'accéder aux variables privées
           temp.element;
           temp.next;
    }
    Le compilateur me dit que je n'ai pas le droit d'accéder à 'element' et à 'next'.

    Indépendamment du fait qu'on aime ou pas utiliser les fonctions amies, ou les sous classes... j'aimerai comprendre pourquoi ce code ne marche pas. j'ai essayé sans les templates, avec des classes bidons, et ça marche bien...

    Merci d 'avance pour vos réponses

  2. #2
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Etrange... quel compilo?


    Est-ce qu'utiliser :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend ostream& ::operator<<(ostream&, const LinkedList<T>&);
    Marche mieu?

  3. #3
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mai 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2009
    Messages : 26
    Points : 18
    Points
    18
    Par défaut
    J'utilise VS 2008.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend ostream& ::operator<<(ostream&, const LinkedList<T>&);
    ne marche pas... Erreur de compilation.

  4. #4
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    Je n'ai pas ma machine de dev de dispo, est-ce que tu peux essayer ça?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend ostream& operator<< <T>(ostream&, const LinkedList<T>&);
    Si c'est la bonne syntaxe pour préciser le type de l'instance de template?

  5. #5
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mai 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2009
    Messages : 26
    Points : 18
    Points
    18
    Par défaut
    l'opérateur << n'est pas membre de la classe, je ne vois pas pourquoi il faudrait mettre cette syntaxe... j'ai tout de même essayé :-)
    mais ça ne compile pas !

  6. #6
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Le code suivant compile chez moi (g++ 4.4) avec un warning.
    Pas le temps de chercher à virer.

    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
    #include <iostream>
     
    using namespace std;
     
    template<typename T> class LinkedList;
    template <class T>
    ostream& operator<<(ostream& out, const LinkedList<T>& list);
     
    template<typename T>
    class LinkedList
    {
         friend ostream& operator<< <>(ostream&, const LinkedList<T>&);
          template<class>
          class LinkedNode
          {
    	  friend class LinkedList<T>;
    	  friend ostream& operator<<(ostream&, const LinkedList<T>&);
     
          public:
    	  T element;
    	  LinkedNode<T>* next;
          };
     private:
          LinkedNode<T>* head;
          LinkedNode<T>* tail;
    public:
    LinkedList():head(new LinkedNode<T>){head->element=42;}
    ~LinkedList(){delete head;}
    };
     
    template <class T>
    ostream& operator<<(ostream& out, const LinkedList<T>& list)
     {
        typename LinkedList<T>::template LinkedNode<T>* temp = list.head;
           // ce code ne fait rien, j'essaye juste d'accéder aux variables privées
           out<<temp->element;
           //temp.next;
    }
     
    int main(int argc, char const *argv[])
    {
        LinkedList<int> t;
        std::cout<<(t);
        return 0;
    }
    (au passage, ca fait mal de se rendre compte qu'on a rouiller en programmation )
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    En cheminant à partir du code de départ avec le même compilo que toi, j'arrive à reproduire l'erreur d'accès que tu obtiens, mais avec un code faux.

    Je quasi sûr que tu as une erreur dans la déclaration de ta fonction amie; erreur qu'a corrigé Davidbrcz dans sa soluce complète.
    La fonction "amie" que tu définis ne correspond pas au profil que tu déclares.

    tu déclares
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>
    class LinkedList
    {
      friend ostream& operator<<(ostream&, const LinkedList<T>&);
      ...
    Ce n'est pas le profil d'une fonction template.

    Et tu veux lui faire correspondre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <typename T>
    ostream& operator<<(ostream& out, const LinkedList<T>& list)
    {...}
    Qui elle est est template, mais qui ne correspond pas à la déclaration d'amitié du coup. D'où la violation d'accès.

    Si tu regardes de plus près le code de David sa déclaration d'amitié diffère:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>
    class LinkedList
    {
      friend ostream& operator<< <> (ostream&, const LinkedList<T>&);
      ...
    C'est le chevron <> qui fait toute la différence, car l'ami au lieu d'être une fonction simple est maintenant une fonction template totalement spécialisée.

  8. #8
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Citation Envoyé par Jan Rendek Voir le message
    En cheminant à partir du code de départ avec le même compilo que toi, j'arrive à reproduire l'erreur d'accès que tu obtiens, mais avec un code faux.

    Je quasi sûr que tu as une erreur dans la déclaration de ta fonction amie; erreur qu'a corrigé Davidbrcz dans sa soluce complète.
    La fonction "amie" que tu définis ne correspond pas au profil que tu déclares.

    tu déclares
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>
    class LinkedList
    {
      friend ostream& operator<<(ostream&, const LinkedList<T>&);
      ...
    Ce n'est pas le profil d'une fonction template.

    Et tu veux lui faire correspondre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <typename T>
    ostream& operator<<(ostream& out, const LinkedList<T>& list)
    {...}
    Qui elle est est template, mais qui ne correspond pas à la déclaration d'amitié du coup. D'où la violation d'accès.

    Si tu regardes de plus près le code de David sa déclaration d'amitié diffère:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>
    class LinkedList
    {
      friend ostream& operator<< <> (ostream&, const LinkedList<T>&);
      ...
    C'est le chevron <> qui fait toute la différence, car l'ami au lieu d'être une fonction simple est maintenant une fonction template totalement spécialisée.
    ca change rien au warning que j'ai et dont je n'ai pas la moindre idée sur sa provenance. Si un guru (luc, marc) passait passait par là, pourrait t'il m'expliquer ?
    Merci.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  9. #9
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mai 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2009
    Messages : 26
    Points : 18
    Points
    18
    Par défaut
    Merci pour vos réponses, pour l'instant, même avec la solution donnée, mon problème n'est pas résolu, mais grâce à vos explications, je commence à le situer un peu mieux. J'y passerai un moment cette après midi, et je vous tiendrai au courant !

  10. #10
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Citation Envoyé par Benlev Voir le message
    Merci pour vos réponses, pour l'instant, même avec la solution donnée, mon problème n'est pas résolu, mais grâce à vos explications, je commence à le situer un peu mieux. J'y passerai un moment cette après midi, et je vous tiendrai au courant !
    Qu'est ce qui ne marche pas ?
    Car mon code compilez chez moi.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  11. #11
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mai 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2009
    Messages : 26
    Points : 18
    Points
    18
    Par défaut
    La raison pour laquelle le code de Davidbrcz compile (et le mien non), est toute simple:
    les variables de la classe LinkedNode sont en public : le même problème que dans mon code se pose si on les met en private...


    EDIT:
    mes excuses, effectivement ce que je viens d'écrire est vrai, mais c'est uniquement parce qu'il manque une toute petite chose dans son code:

    je me demandais pourquoi il fallait mettre <> uniquement dans LinkedList, et non dans LinkedNode : la réponse est qu'il ne faut pas !

    en mettant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    friend ostream& operator<< <> (...);
    le code compile.

    Voici donc le code complet :
    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
    #include <iostream>
     
    using namespace std;
     
    template<typename T>
    class LinkedList
    {
    	friend ostream& operator<< <>(ostream&, const LinkedList<T>&);
    	template<typename>
    	class LinkedNode
    	{
    		friend class LinkedList<T>;
    		friend ostream& operator<< <>(ostream&, const LinkedList<T>&);
     
    	private:
    		T element;
    		LinkedNode<T>* next;
    	};
    private:
    	LinkedNode<T>* head;
    	LinkedNode<T>* tail;
    public:
    	LinkedList():head(new LinkedNode<T>){head->element=42;}
    	~LinkedList(){delete head;}
    };
     
    template <typename T>
    ostream& operator<<(ostream& out, const LinkedList<T>& list)
    {
    	LinkedList<T>::LinkedNode<T>* temp = list.head;
    	out<<temp->element;
    	return out;
    }
     
     
    int main(int argc, char const *argv[])
    {
    	LinkedList<int> t;
    	std::cout<<t;
    	return 0;
    }

  12. #12
    Membre confirmé Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Points : 633
    Points
    633
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message
    ca change rien au warning que j'ai et dont je n'ai pas la moindre idée sur sa provenance. Si un guru (luc, marc) passait passait par là, pourrait t'il m'expliquer ?
    Merci.
    Peut-être est-ce a cause de la spécialisation partielle ?
    J'aurais plutôt tendance à ecrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    friend ostream& operator<< <T>(...)
    Ou même aucune spécialisation...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template <typename U>
    friend ostream& operator<< (...)
    Mais c'est vrai que c'est un peu redondant... Quel warning est-ce exactement ?
    The mark of the immature man is that he wants to die nobly for a cause, while the mark of the mature man is that he wants to live humbly for one.
    --Wilhelm Stekel

  13. #13
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mai 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2009
    Messages : 26
    Points : 18
    Points
    18
    Par défaut
    Avec le code donné précédemment et VS 2008 comme compilo, je n'ai pas de warning...

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    test.cpp:17: warning: friend declaration `std::ostream& operator<<(std::ostream&, const LinkedList<T>&)' declares a non-template function
    test.cpp:17: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disab
    les this warning
    La déclaration d'amitié est fausse L17. Il faut aussi déclarer une fonction template comme le fait justement remarquer l'OP, les membres de la structure interne sont publics, donc pas de pb d'accès.
    Ce n'est pas une erreur en soit, car peut créer une famille de fonction non-template par surcharge des parametres, genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ostream& operator<< (ostream&, const LinkedList<char>&);
    ostream& operator<< (ostream&, const LinkedList<int>&);
    ostream& operator<< (ostream&, const LinkedList<float>&);
    ...
    G++ doit penser que dans la majeure partie des cas, quand la déclaration d'une fonction amie dans une classe template dépend des paramètres d'instanciation, l'utilisateur souhaite faire de la spécialisation.

    Du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<> ostream& operator<< <char>(ostream& out, const LinkedList<char>& list)
    template<> ostream& operator<< <int>(ostream& out, const LinkedList<int>& list)
    template<> ostream& operator<< <float>(ostream& out, const LinkedList<float>& list)
    Le warning en simplifié:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<typename T>
    class A
    {
         friend void f (A<T>);
    };
     
    int main()
    {
        A<int> a;
    }

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

Discussions similaires

  1. nested class dans un class template
    Par bertry dans le forum Langage
    Réponses: 3
    Dernier message: 28/01/2011, 14h21
  2. Méthode template dans classe non template ?
    Par shenron666 dans le forum Langage
    Réponses: 12
    Dernier message: 04/09/2006, 17h50
  3. Question de Nested Classes
    Par CaptnB dans le forum Langage
    Réponses: 2
    Dernier message: 14/07/2006, 23h06
  4. Template et classe "amie" ?
    Par tintin72 dans le forum Langage
    Réponses: 21
    Dernier message: 11/07/2006, 22h50
  5. [C++] - Nested classes?
    Par vdumont dans le forum C++
    Réponses: 5
    Dernier message: 01/03/2006, 10h33

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