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 :

Opérateur indépendant dans un template


Sujet :

Langage C++

  1. #1
    Membre averti Avatar de Razgriz
    Profil pro
    Professeur / chercheur en informatique / mathématiques
    Inscrit en
    Avril 2006
    Messages
    391
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Professeur / chercheur en informatique / mathématiques

    Informations forums :
    Inscription : Avril 2006
    Messages : 391
    Points : 306
    Points
    306
    Par défaut Opérateur indépendant dans un template
    Bonjour à tous,

    j'essaye de concevoir un template pour une classe A<T> dans lequel je veux implémenter les fonctions suivantes (code minimal détaillé ci-dessous) :
    1. un constructeur explicit qui prend un T en paramètre (le fait qu'il soit explicit est important pour mon "vrai" code)
    2. un opérateur + (membre) me permettant de faire un + entre un A et un T
    3. un opérateur + (indépendant) me permettant de faire un + entre un T et un A


    Vous trouverez un code minimal ci-dessous.

    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
    #include <iostream>
     
    template<class T> class A;
     
    template<class T> std::ostream& operator<<(std::ostream&, const A<T>&);
    template<class T> A<T> operator+(const T&, const A<T>&);
     
    template<class T>
    class A
    {
    	T i;
    	public:
    		explicit A(T t) : i(t) {}
     
    		A operator +(A<T> a) const
    		{
    			return A(a.i + i);
    		}
     
    		A operator +(T t) const 
    		{ 
    			return A(i + t); 
    		}
     
     
    		friend std::ostream& operator<< <>(std::ostream& out, const A<T>& a);
    		friend A<T> operator+ <>(const T& t, const A<T>& a);		
    };
     
    template<class T>
    std::ostream& operator<<(std::ostream& out, const A<T>& a)
    {
    	out << a.i;
    	return out;
    }
     
    template<class T>
    A<T> operator +(const T& t, const A<T>& a)
    {
    	return a + t;
    }
     
    int main()
    {
    	A<int> b(2);
          	std::cout << (b + 2) << std::endl;
    	std::cout << (2 + b) << std::endl;
    }
    Problème : le compilateur m'envoie balader, en me disant que je déclare un opérateur + comme une "non-function", ce qui est ... exactement ce que je veux faire.
    J'ai déclaré une amitié pour cet opérateur de la même manière que pour l'injection << dans les flux, mais a priori, ça ne marche pas.

    Évidemment, si j'enlève le '<>' dans la déclaration d'amitié, j'ai un warning me disant que je déclare une fonction non-template, ce qui n'est pas ce que je veux.

    Que dois-je faire ? Pour rappel, je ne veux pas concevoir de constructeur non explicit (ce qui me permettrait de faire des conversions implicites d'un T vers un A et je n'aurais pas de problème).

    Merci d'avance
    On a toujours besoin d'un plus bourrin que soi

    Oui il y a quelques bugs dans ma librairie de Sécurité, mais les classes postées ne sont pas celles de la dernière version, et j'ai la flemme de tout modifier. Je vous donnerai avec plaisir la dernière version du jar par mp.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Salut,

    bien que n'ayant jamais rencontré de syntaxe aussi alambiquée, la déclaration ne devrait pas être friend template<class T> A<T> operator +(const T& t, const A<T>& a) ou bien template<> A<T> operator +(const T& t, const A<T>& a) ?
    Puisque généralement il s'agit d'écrire friend <<prototype>>.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre averti Avatar de Razgriz
    Profil pro
    Professeur / chercheur en informatique / mathématiques
    Inscrit en
    Avril 2006
    Messages
    391
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Professeur / chercheur en informatique / mathématiques

    Informations forums :
    Inscription : Avril 2006
    Messages : 391
    Points : 306
    Points
    306
    Par défaut
    Les lignes 5 et 6 sont des déclarations de fonctions templates indépendantes, où il est nécessaire de préciser que T est une classe, ce qui est fait. Il n'y a a priori pas de problèmes sur ces lignes.

    La déclaration d'amitié de cette fonction envers la classe A doit néanmoins se faire au sein de A, car c'est une classe qui déclare qui « est son ami », permettant ainsi d'accéder aux attributs privés directement. C'est cette déclaration d'amitié qui est incorrecte pour le compilateur.

    Cette syntaxe est celle présente sur cppreference (avant dernier code). Je n'ai toutefois pas une grande expérience en C++, je suis donc aussi assez preneur d'une alternative plus élégante.
    On a toujours besoin d'un plus bourrin que soi

    Oui il y a quelques bugs dans ma librairie de Sécurité, mais les classes postées ne sont pas celles de la dernière version, et j'ai la flemme de tout modifier. Je vous donnerai avec plaisir la dernière version du jar par mp.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Si je m'en tiens au code de cppreference en l'adaptant j'écrirais friend A operator+ <>(const T& t, const A& a);, ce qui n'est toujours pas ta syntaxe originale.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre averti Avatar de Razgriz
    Profil pro
    Professeur / chercheur en informatique / mathématiques
    Inscrit en
    Avril 2006
    Messages
    391
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Professeur / chercheur en informatique / mathématiques

    Informations forums :
    Inscription : Avril 2006
    Messages : 391
    Points : 306
    Points
    306
    Par défaut
    Les <..> sont implicites au sein d'une classe déclarée template : les écrire est redondant, mais pas une erreur. Je les écris pour me rappeler de ce avec quoi je traite. Aussi, les erreurs à la compilation sont exactement les mêmes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    brol.cpp:27:20: error: declaration of ‘operator+’ as non-function
       friend A operator+ <>(const T& t, const A& a);  
                        ^
    brol.cpp:27:20: error: expected ‘;’ at end of member declaration
    brol.cpp:27:22: error: expected unqualified-id before ‘<’ token
       friend A operator+ <>(const T& t, const A& a);  
                          ^
    On a toujours besoin d'un plus bourrin que soi

    Oui il y a quelques bugs dans ma librairie de Sécurité, mais les classes postées ne sont pas celles de la dernière version, et j'ai la flemme de tout modifier. Je vous donnerai avec plaisir la dernière version du jar par mp.

  6. #6
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Citation Envoyé par Razgriz Voir le message
    Les <..> sont implicites au sein d'une classe déclarée template : les écrire est redondant, mais pas une erreur.
    Pas pour une fonction amie qui, même si elle est déclaré dans une classe ne fait pas partie de celle-ci.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template<class U>
    friend A<U> operator+ (const U& t, const A<U>& a);

  7. #7
    Membre averti Avatar de Razgriz
    Profil pro
    Professeur / chercheur en informatique / mathématiques
    Inscrit en
    Avril 2006
    Messages
    391
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Professeur / chercheur en informatique / mathématiques

    Informations forums :
    Inscription : Avril 2006
    Messages : 391
    Points : 306
    Points
    306
    Par défaut
    C'est en effet vrai (et c'est ce qui était fait dans le post original), mais comme mentionné dans le post original, si je déclare mon amitié comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend A<T> operator+ (const T& t, const A<T>& a);
    le compilateur m'affiche un warning justifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    warning: friend declaration ‘A<T> operator+(const T&, const A<T>&)’ declares a non-template function [-Wnon-template-friend]
       friend A<T> operator+ (const T& t, const A<T>& a);  
                                                       ^
    brol.cpp:27:51: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
    (Notez le prototype de l'opérateur << )
    On a toujours besoin d'un plus bourrin que soi

    Oui il y a quelques bugs dans ma librairie de Sécurité, mais les classes postées ne sont pas celles de la dernière version, et j'ai la flemme de tout modifier. Je vous donnerai avec plaisir la dernière version du jar par mp.

  8. #8
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Ah ok, je viens de comprendre. Visiblement, les opérateurs + en membre rentrent en conflit avec l'amitié. Aucune idée du pourquoi Oo.
    Avec que des fonctions libre, cela devraient passer.

  9. #9
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 642
    Points
    7 642
    Par défaut
    Curieux, qu'il interprète operator+ <>( sans voir la déclaration d'une fonction.
    Et en ajoutant des parenthèses (operator+ <>)( ou bien (::operator+ <>)( ?

  10. #10
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Si on déplace la déclaration de l'amitié avant celle des opérateurs, ça compile Oo

  11. #11
    Membre averti Avatar de Razgriz
    Profil pro
    Professeur / chercheur en informatique / mathématiques
    Inscrit en
    Avril 2006
    Messages
    391
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Professeur / chercheur en informatique / mathématiques

    Informations forums :
    Inscription : Avril 2006
    Messages : 391
    Points : 306
    Points
    306
    Par défaut
    Wtf ?!

    Bon... ça marche. Qqn a une idée, même lointaine, de pourquoi il faut déclarer l'amitié avant la déclaration du prototype ?
    On a toujours besoin d'un plus bourrin que soi

    Oui il y a quelques bugs dans ma librairie de Sécurité, mais les classes postées ne sont pas celles de la dernière version, et j'ai la flemme de tout modifier. Je vous donnerai avec plaisir la dernière version du jar par mp.

  12. #12
    Invité
    Invité(e)
    Par défaut
    À mon avis les opérateurs membres dans la classe étant plus proches au niveau scope, ils sont privilégiés par rapport au bon, et le compilateur tente alors de les spécialiser en vain.
    Et lorsque l'on déplace notre ligne avant, ces derniers ne sont pas encore introduits, et le compilateur n'a d'autre choix que de sélectionner la seule qu'il connait.

    Preuve en est faite, si comme proposé par dalfab on modifie la ligne pour faire explicitement référence à l'opérateur situé à l'extérieur de la classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    friend A<T> (::operator+ <>) (const T& t, const A<T>& a);
    cela compile également.

    Maintenant, pourquoi y a-t-il prise en compte des opérateurs membres sur la déclaration d'un opérateur friend libre, ça me dépasse.

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

Discussions similaires

  1. PB de balises dans un template récursif ?
    Par Kyti dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 26/05/2006, 09h44
  2. [DreamWeaver]Les liens dans ma template .dwt
    Par mamiberkof dans le forum Dreamweaver
    Réponses: 2
    Dernier message: 14/04/2006, 18h12
  3. Champ indépendant dans sous-formulaire
    Par lito74 dans le forum Access
    Réponses: 7
    Dernier message: 27/01/2006, 16h57
  4. [XSL] Passage de variable dans un template
    Par Otarie dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 14/11/2005, 23h50
  5. cast dans un template
    Par olivic dans le forum Langage
    Réponses: 15
    Dernier message: 20/10/2004, 14h10

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