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 :

Passage de visual à linux: erreur étrange de template


Sujet :

C++

  1. #1
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut Passage de visual à linux: erreur étrange de template
    Bonjour,

    j'ai récemment installé Linux, et g++ (version 4.2), et en compilant ce programme:

    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
    #include <iostream>
     
    template <class T>
    class smart_ptr
    {
    public:
        T data;
    	int i;
     
    	virtual int get_data() { return i; }
    };
     
    template <class T>
    class wrapper : public smart_ptr<T>
    {
    	virtual int get_data() {return i; }
    };
     
    int main()
    {
    	std::cout << "Hello world!" << std::endl;
    	return 0;
    }
    J'ai une erreur: "i was not declared in this scope" pour la fonction get_data() de wrapper.

    Si au lieu de mettre public: smart_ptr<T> je mets un type non template tout va bien (mais j'ai besoin des templates!!)

    Pour réussir à le faire passer je dois faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class T>
    class wrapper : public smart_ptr<T>
    {
    	virtual int get_data() {return smart_ptr<T>::i; }
    };
    C'est moche!

    Est-ce que j'ai loupé une option de compilation quelque part, parce que je trouve ça vraiment louche?

    Merci

  2. #2
    Membre régulier Avatar de thoratou
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Points : 116
    Points
    116
    Par défaut
    Ah mon avis, le compilateur Linux veut se protéger d'une spécification de smart_ptr ne possédant pas d'attribut public i. Typiquement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template<>
    class smart_ptr<maClasse>
    {
    public:
    	virtual int get_data() { return 1; }
    };
    Il demande ainsi d'indiquer explicitement d'où provient la variable i et laisse donc la responsabilité au programmeur de ne spécifier que des smart_ptr avec un attribut i.
    Screen (SCalable REndering ENgine) : moteur 3d en développement

    There are only two things wrong with C++: The initial concept and the
    implementation.
    Bertrand Meyer

  3. #3
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Citation Envoyé par thoratou Voir le message
    Ah mon avis, le compilateur Linux veut se protéger d'une spécification de smart_ptr ne possédant pas d'attribut public i. Typiquement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template<>
    class smart_ptr<maClasse>
    {
    public:
    	virtual int get_data() { return 1; }
    };
    Il demande ainsi d'indiquer explicitement d'où provient la variable i et laisse donc la responsabilité au programmeur de ne spécifier que des smart_ptr avec un attribut i.
    Tout à fait.
    Et si tu te sers de i à plusieurs endroits, un :
    à l'intérieur de la déclaration de la classe devrait faire l'affaire, pour que tu n'ais plus à écrire "smart_ptr<T>::" devant à chaque fois.

  4. #4
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Et avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <class T>
    class wrapper : public smart_ptr<T>
    {
    	virtual int get_data() {return this->i; }
    };
    ?
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  5. #5
    Membre régulier Avatar de thoratou
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Points : 116
    Points
    116
    Par défaut
    C'est toujours la même chose.

    Le compilateur a besoin de "passer un contrat" disant :

    Je vais chercher l'attribut i de smart_ptr seulement si tu m'assures que smart_ptr contiendra toujours un attribut i. Ce contrat est passer dans les 2 cas présentés précédemment :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return smart_ptr<T>::i;
    ou

    dans ces 2 cas, si tu spécifies un smart_ptr sans un attribut i, tu auras une erreur de compilation.

    Le compilteur Visual est "malheureusement" plus souple, et il résoudra explicitement ce genre de dépendance sans "passer de contrat". Imagine maintenant le cas suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <class T>
    class wrapper : public smart_ptr<T>, public autreClasse<T>
    {
    	virtual int get_data() {return i; }
    };
    Dans ce cas avec héritage multiple, on ne peut pas savoir d'où provient i.
    Alors qu'en ecrivant ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    template <class T>
    class wrapper : public smart_ptr<T>, public autreClasse<T>
    {
    	using smart_ptr<T>::i;
    	virtual int get_data() {return i; }
    };
    le contrat est passé, on s'engage à ce que smart_ptr possède systématiquement un attribut i

    EDIT :
    Je ne parle pas de contrat par hasard, c'est à relier à la programmation par contrat. Il doit exister de nombreux cours, notamment sur le langage Ada est parfait pour apprendre la programmation par contrat.

    En C++, il y a des manques :
    - Absence d'un mot clef type 'interface' en Java. Beaucoup de développeurs C++ sont passé par le java et reprennent donc le même concepts avec les classes dites 'abstraites pures'
    - Absence de contrat pour les types paramétrés dans la syntaxe du langage. Les compilateurs s'arrangent, ce qui donne les différences obtenues ici entre Visual et Linux. Le nouveau standard C++0x devrait rectifier le tir avec la notion de 'concept'.
    Screen (SCalable REndering ENgine) : moteur 3d en développement

    There are only two things wrong with C++: The initial concept and the
    implementation.
    Bertrand Meyer

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Pour moi la meilleure solution reste celle de seriousme. C'est d'ailleurs cette dernière qui est préconisé dans "C++ Templates: The Complete Guide".

    PS: pour ceux que ça intéresse je conseille la lecture du post de James Kanze dans ce thread

  7. #7
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Merci, le "using" est une solution acceptable

    Mais sur ce coup-là je trouve que Visual est bien meilleur, d'ailleurs si g++ ne s'occupait que des template qui sont initialisés dans le code (initialisation paresseuse) au lieu de faire dans le générique il n'y aurait aucun problème...

    Et puis même dans le générique il est dans un cas dans lequel il peut tout déterminer, et ne devrait lancer une erreur que dans le cas d'une ambiguïté .

    En tout cas merci de vos réponses, problème résolu

  8. #8
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Citation Envoyé par thoratou Voir le message
    - Absence de contrat pour les types paramétrés dans la syntaxe du langage. Les compilateurs s'arrangent, ce qui donne les différences obtenues ici entre Visual et Linux. Le nouveau standard C++0x devrait rectifier le tir avec la notion de 'concept'.
    Raté, vas voir dans C++ > Communauté.
    Ca sera éventuellement dans celui d'après...

  9. #9
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    He ben non... les concepts on était retiré de la prochaine norme .
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  10. #10
    Membre régulier Avatar de thoratou
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Points : 116
    Points
    116
    Par défaut
    Pour répondre à MonTag, la solution du this ne me semble pas la meilleure

    Si on reprend le cas de l'héritage multiple avec chacun des parents possédant un attribut i, le this ne permettra pas de déterminer lequel est utilisé.
    Autant prendre directement les bonnes habitudes.

    Par contre c'est vraiment dommage pour les concepts, je pense que ça aurait été une bonne chose
    Screen (SCalable REndering ENgine) : moteur 3d en développement

    There are only two things wrong with C++: The initial concept and the
    implementation.
    Bertrand Meyer

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Citation Envoyé par thoratou Voir le message
    Pour répondre à MonTag, la solution du this ne me semble pas la meilleure

    Si on reprend le cas de l'héritage multiple avec chacun des parents possédant un attribut i, le this ne permettra pas de déterminer lequel est utilisé.
    Autant prendre directement les bonnes habitudes.

    Par contre c'est vraiment dommage pour les concepts, je pense que ça aurait été une bonne chose
    Et quand le nom de la classe de base est super long tu fais quoi ? Tu vas écrire à chaque fois ma_classe_de_base<T, R, S>::member ? Franchement c'est horrible, le C++ est déjà suffisamment verbeux sans en plus en rajouter. D'ailleurs une recherche rapide dans le code de boost me conforte dans l'idée que le this-> est la meilleure solution.
    Imagine que l'auteur de ce code (tiré de boost::asio) ait été de ton avis ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template <typename Protocol, typename Reactor>
    class reactive_socket_service
      : public boost::asio::detail::service_base<
          reactive_socket_service<Protocol, Reactor> >
    {
    ...
    };
    Quand à l'argument sur l'héritage multiple je ne vois pas trop où tu veux en venir. Que préconises-tu ? De qualifier le membre d'une classe base à chaque fois que l'on veux y accéder ?

  12. #12
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Il y a quelque chose qui me chiffonne

    Si le compilateur est content avec un this-> (qui ne précise pas du tout d'où vient la variable), alors pourquoi sans le this-> ça ne marche pas? Pour avoir des messages d'erreurs plus explicites?

    Sinon:

    Citation Envoyé par Montag
    Tu vas écrire à chaque fois ma_classe_de_base<T, R, S>::member ?
    thoratou a aussi proposé cette solution:

    Citation Envoyé par thoratou
    Enfin bref pour en revenir au problème dans mon cas en pratique chaque classe dérivée appelait des paramètres template différents (le plus souvent dérivés des paramètres templates de la classe de base) donc l'héritage ne servait pas à grand chose vu la manière dont le code était dupliqué. (j'ai quand même fait une classe de base ultra-basique sans templates, mais c'est tout)

    Mais j'aurais appris quelque chose

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Citation Envoyé par coyotte507 Voir le message
    Il y a quelque chose qui me chiffonne

    Si le compilateur est content avec un this-> (qui ne précise pas du tout d'où vient la variable), alors pourquoi sans le this-> ça ne marche pas? Pour avoir des messages d'erreurs plus explicites?
    Dans mon premier message j'ai donné un lien vers un thread dans lequel James Kanze explique très bien le problème.

    Citation Envoyé par coyotte507 Voir le message
    thoratou a aussi proposé cette solution:
    Bof, injecter des noms dans le scope de la classe dérivée j'aime pas trop.

  14. #14
    Membre régulier Avatar de thoratou
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Points : 116
    Points
    116
    Par défaut
    le problème avec le this est que le compilateur fait une sorte de cast implicite pour trouver d'où vient l'attribut.
    Par exemple ici le this est casté de const wrapper<T> const * en const smart_ptr<T> const *.

    Ce genre de mécanisme est à prohiber : un contrat doit être correctement explicité, même si le C++ est un peut casse gueule pour se genre de chose

    Dans le cas d'héritage multiple avec 2 classes héritées possédant un attribut i, quelle attribut sera choisi ?
    Réponse : ça dépend de l'implémentation du compilateur, puisque c'est lui qui décide du cast à effectuer (ou éventuellement il peut faire un joli message d'erreur).

    La solution smart_ptr<T>::i (avec ou sans using) est la seule sans ambiguïté et avec un contrat clairement explicité.

    Et effectiviement, même si le nom de la classe est super long, je met quand même le nom plutôt qu'un this.

    Après si ca te suffit de te contenter de la réponse "c'est machin bidule qui a écrit ça dans son livre", alors continue avec this
    Screen (SCalable REndering ENgine) : moteur 3d en développement

    There are only two things wrong with C++: The initial concept and the
    implementation.
    Bertrand Meyer

  15. #15
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Je ne sais pas d'où tu sors tes histoires de cast implicite ni de quel contrat tu veux parler mais bon...
    En ce qui concerne l'héritage multiple je ne comprends toujours pas ton argument. Quand, dans une méthode d'une classe dérivée, tu fais référence à un membre d'une classe de base tu le qualifies systématiquement ?

    Toujours est-il que je continuerai à utiliser this-> non pas comme tu le prétends parce que je l'ai lu dans un livre mais bien parce que cette solution me parait être la plus élégante.

  16. #16
    Membre régulier Avatar de thoratou
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Points : 116
    Points
    116
    Par défaut
    Bon je vais alors faire un exemple 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
     
    template <class T>
    class smart_ptr{
    public:
        int i;
        ....
    };
     
     
    template <class T>
    class autreClasse{
    public:
        int i;
        ....
    };
     
    template <class T>
     
    template <class T>
    class wrapper : public smart_ptr<T>, public autreClasse<T>{
        virtual int get_data() {return this->i; }
    };
    Peut-tu me dire quel attribut i sera utilisé ?
    Screen (SCalable REndering ENgine) : moteur 3d en développement

    There are only two things wrong with C++: The initial concept and the
    implementation.
    Bertrand Meyer

  17. #17
    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
    Ca ne compilera même pas non? Autrement dit l'erreur est difficile a rater dans ce genre de cas. - VC9 me donne bien une erreur d'ambiguïté sur i.

    Il n'y a que si il y avait un i dans un scope plus proche (membre ou locale) que l'ambiguité serait automatiquement résolue.

  18. #18
    Membre régulier Avatar de thoratou
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Points : 116
    Points
    116
    Par défaut
    Exactement, d'où le smart_ptr<T>::i plutôt que this->i

    Dans le cas de smart_ptr<T>::i, pas d'ambiguïté
    Screen (SCalable REndering ENgine) : moteur 3d en développement

    There are only two things wrong with C++: The initial concept and the
    implementation.
    Bertrand Meyer

  19. #19
    Membre actif
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Points : 219
    Points
    219
    Par défaut
    Citation Envoyé par thoratou Voir le message
    Bon je vais alors faire un exemple 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
     
    template <class T>
    class smart_ptr{
    public:
        int i;
        ....
    };
     
     
    template <class T>
    class autreClasse{
    public:
        int i;
        ....
    };
     
    template <class T>
     
    template <class T>
    class wrapper : public smart_ptr<T>, public autreClasse<T>{
        virtual int get_data() {return this->i; }
    };
    Peut-tu me dire quel attribut i sera utilisé ?
    Evidemment que dans le cas de l'héritage multiple ça ne fonctionnera pas. Le problème c'est que tu utilises le cas de l'héritage multiple pour justifier l'emploi de smart_ptr<T>:: dans le cas de l'héritage "simple" et là, je ne suis pas d'accord. En effet si on suit tes conseils il faudrait faire ça :
    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 Base
    {
    public:
        int i;
        ....
    };
     
    class Derived : public Base
    {
    public:
        int get_i()
        {
            return Base::i;
        }
    };
    Et ça c'est...

  20. #20
    Membre régulier Avatar de thoratou
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Décembre 2008
    Messages : 57
    Points : 116
    Points
    116
    Par défaut
    ... inutile

    Dans ce cas d'heritage simple, le contrat est explicité : "je suis la classe Derive, je suis sûr que Base possède un attribut i puisque Base est clairement défini".

    Dans le cas avec patron, on peut spécifier n'importe quelle spécialisation de la classe, ne possèdant eventuellement pas d'attribut i. Dans ce cas là, la contrat n'est pas explicité, d'où le smart_ptr<i>::i qui dit "on oblige que toutes définitions de smart_ptr possède un attribut i".
    Screen (SCalable REndering ENgine) : moteur 3d en développement

    There are only two things wrong with C++: The initial concept and the
    implementation.
    Bertrand Meyer

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

Discussions similaires

  1. erreur de link au passage de visual studio 2005 vers 2008
    Par blueLight dans le forum Visual C++
    Réponses: 2
    Dernier message: 21/04/2008, 15h02
  2. [ 3.1 ] [ Linux ] Erreur au démarrage
    Par lr dans le forum Eclipse Java
    Réponses: 14
    Dernier message: 28/09/2005, 23h18
  3. [Visual Fortran] Erreur de compilation
    Par Julito dans le forum Fortran
    Réponses: 1
    Dernier message: 04/03/2005, 21h24
  4. Erreur étrange sur recvfrom
    Par Gore dans le forum Développement
    Réponses: 2
    Dernier message: 17/02/2005, 12h22
  5. Réponses: 4
    Dernier message: 27/08/2003, 21h34

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