bonjour à tous
je me suis bien pris la tête sur un truc l'autre jour, alors pour que
les choses soient plus claires dans ma tête je vous l'expose dans
l'espoir que l'un d'entre vous m'éclaire
j'ai une classe définie dans un namespace
et je veux surcharger l'operateur >> de istream
la classe comportant des membres prives je suis obligé de déclarer
operator>> comme fonction amie.
voici le code correspondant
namespace Espace{
class Foo{
friend istream& operator>>(istream&, Foo&);
public:
int getA();
private:
int a;
};
}
et dans le cpp correspondant:
int Espace::Foo::getA()
{
return a;
}
istream& operator>>(istream& is, Espace::Foo& f)//compile pas
//istream& Espace::operator>>(istream& is, Espace::Foo& f)//compile
{
is>> f.a;
return is;
}
et là ça ne compile pas avec la premiere ligne, pour un acces à un
membre privé de Foo
si je met la deuxieme ligne pas de souci
donc ma question c'est pourquoi?
je présume que la déclaration friend revient plus ou moins à un extern,
mais pourquoi l'ajoute t'il dans le namespace Espace?
Y a t'il un moyen de l'éviter?
(c'est compilé avec MSVC7 si ça a une importance)
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Falk Tannhäuser
Nico R wrote:
namespace Espace{ class Foo{
friend istream& operator>>(istream&, Foo&);
public: int getA(); private: int a;
}; }
et dans le cpp correspondant:
J'aurais écrit namespace Espace { int Foo::getA() { return a; } std::istream& operator>>(std::istream& is, Foo& f) { return is >> f.a; } } mais ça revient au même - l'opérateur>> en question se retrouve dans le namespace Espace. Cela ne pose AMA aucun problème - si tu fais
int main() { Espace::Foo f; std::cin >> f; ...
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig lookup", cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les namespaces std et Espace, donc il sera trouvé dans ce dernier.
je présume que la déclaration friend revient plus ou moins à un extern, mais pourquoi l'ajoute t'il dans le namespace Espace? Y a t'il un moyen de l'éviter?
Je ne vois pas trop pourquoi l'éviter, mais c'est possible :
namespace Espace { class Foo; } // Déclaration sans définition de Foo std::istream& operator>>(std::istream&, Espace::Foo&); // Déclaration de l'opérateur>> dans le namespace global
namespace Espace { class Foo { friend std::istream& ::operator>>(std::istream&, Foo&); // Noter le :: ^^ ! ...
puis on définit cet opérateur dans le .C au niveau du namespace global...
Falk
Nico R wrote:
namespace Espace{
class Foo{
friend istream& operator>>(istream&, Foo&);
public:
int getA();
private:
int a;
};
}
et dans le cpp correspondant:
J'aurais écrit
namespace Espace
{
int Foo::getA() { return a; }
std::istream& operator>>(std::istream& is, Foo& f) { return is >> f.a; }
}
mais ça revient au même - l'opérateur>> en question se retrouve dans le
namespace Espace. Cela ne pose AMA aucun problème - si tu fais
int main()
{
Espace::Foo f;
std::cin >> f;
...
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig lookup",
cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les namespaces
std et Espace, donc il sera trouvé dans ce dernier.
je présume que la déclaration friend revient plus ou moins à un extern,
mais pourquoi l'ajoute t'il dans le namespace Espace?
Y a t'il un moyen de l'éviter?
Je ne vois pas trop pourquoi l'éviter, mais c'est possible :
namespace Espace { class Foo; } // Déclaration sans définition de Foo
std::istream& operator>>(std::istream&, Espace::Foo&);
// Déclaration de l'opérateur>> dans le namespace global
namespace Espace
{
class Foo
{
friend std::istream& ::operator>>(std::istream&, Foo&);
// Noter le :: ^^ !
...
puis on définit cet opérateur dans le .C au niveau du namespace global...
J'aurais écrit namespace Espace { int Foo::getA() { return a; } std::istream& operator>>(std::istream& is, Foo& f) { return is >> f.a; } } mais ça revient au même - l'opérateur>> en question se retrouve dans le namespace Espace. Cela ne pose AMA aucun problème - si tu fais
int main() { Espace::Foo f; std::cin >> f; ...
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig lookup", cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les namespaces std et Espace, donc il sera trouvé dans ce dernier.
je présume que la déclaration friend revient plus ou moins à un extern, mais pourquoi l'ajoute t'il dans le namespace Espace? Y a t'il un moyen de l'éviter?
Je ne vois pas trop pourquoi l'éviter, mais c'est possible :
namespace Espace { class Foo; } // Déclaration sans définition de Foo std::istream& operator>>(std::istream&, Espace::Foo&); // Déclaration de l'opérateur>> dans le namespace global
namespace Espace { class Foo { friend std::istream& ::operator>>(std::istream&, Foo&); // Noter le :: ^^ ! ...
puis on définit cet opérateur dans le .C au niveau du namespace global...
Falk
Nico R
J'aurais écrit namespace Espace { int Foo::getA() { return a; } std::istream& operator>>(std::istream& is, Foo& f) { return is >> f.a; } } mais ça revient au même
merci pour ta reponse l'assesseur n'était pas inline parce que j'en ai juste mis un dans mon exemple pour qu'il y ait une fonction membre. par contre l'operateur inline comme ça ça marche? parce que là en fait tu le déclares comme une fonction membre du coup ce n'est pas vraiment une surcharge de std::operator>>, i.e. je ne suis pas sur que je puisse l'appeler comme ça:
Espace::Foo f; cin>>f;
par contre avec un friend devant ça marche, mais je trouve ça super crade. enfin c'est mes automatismes de développeurs Java, je suis pas super habitué à la surcharge d'operateurs...
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig lookup", cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les namespaces std et Espace, donc il sera trouvé dans ce dernier.
faudrait que je lise cette norme. C'est abordable?
C'est dans le Stroustrup ou c'est autre chose? merci pour ta réponse
J'aurais écrit
namespace Espace
{
int Foo::getA() { return a; }
std::istream& operator>>(std::istream& is, Foo& f) { return is >>
f.a; }
}
mais ça revient au même
merci pour ta reponse
l'assesseur n'était pas inline parce que j'en ai juste mis un dans mon
exemple pour qu'il y ait une fonction membre. par contre l'operateur
inline comme ça ça marche? parce que là en fait tu le déclares comme
une fonction membre du coup ce n'est pas vraiment une surcharge de
std::operator>>, i.e. je ne suis pas sur que je puisse l'appeler comme ça:
Espace::Foo f;
cin>>f;
par contre avec un friend devant ça marche, mais je trouve ça super
crade. enfin c'est mes automatismes de développeurs Java, je suis pas
super habitué à la surcharge d'operateurs...
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig
lookup",
cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les
namespaces
std et Espace, donc il sera trouvé dans ce dernier.
faudrait que je lise cette norme. C'est abordable?
C'est dans le Stroustrup ou c'est autre chose?
merci pour ta réponse
J'aurais écrit namespace Espace { int Foo::getA() { return a; } std::istream& operator>>(std::istream& is, Foo& f) { return is >> f.a; } } mais ça revient au même
merci pour ta reponse l'assesseur n'était pas inline parce que j'en ai juste mis un dans mon exemple pour qu'il y ait une fonction membre. par contre l'operateur inline comme ça ça marche? parce que là en fait tu le déclares comme une fonction membre du coup ce n'est pas vraiment une surcharge de std::operator>>, i.e. je ne suis pas sur que je puisse l'appeler comme ça:
Espace::Foo f; cin>>f;
par contre avec un friend devant ça marche, mais je trouve ça super crade. enfin c'est mes automatismes de développeurs Java, je suis pas super habitué à la surcharge d'operateurs...
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig lookup", cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les namespaces std et Espace, donc il sera trouvé dans ce dernier.
faudrait que je lise cette norme. C'est abordable?
C'est dans le Stroustrup ou c'est autre chose? merci pour ta réponse
Falk Tannhäuser
Nico R wrote:
J'aurais écrit
Le code qui suit était censé se trouver dans le fichier Foo.cpp . Bien sûr, au début il manquait un #include "Foo.H" où le fichier Foo.H contient la définition de la classe Foo dans le namespace Espace, avec les déclarations (sans définition) de la fonction membre getA() et de la fonction "friend" operator>>() .
namespace Espace { int Foo::getA() { return a; } std::istream& operator>>(std::istream& is, Foo& f) { return is >> f.a; } } mais ça revient au même
merci pour ta reponse l'assesseur n'était pas inline parce que j'en ai juste mis un dans mon exemple pour qu'il y ait une fonction membre. par contre l'operateur inline comme ça ça marche? parce que là en fait tu le déclares comme une fonction membre du coup ce n'est pas vraiment une surcharge de std::operator>>, i.e. je ne suis pas sur que je puisse l'appeler comme ça:
Espace::Foo f; cin>>f;
Non, ces 2 fonctions ne sont pas inline - elles sont définies en dehors de la classe Foo (et l'opérateur>> n'est même pas membre de la classe Foo), mais à l'intérieur du namespace Espace, au niveau du fichier Foo.cpp . Mon but était illustrer qu'on peut simplement rouvrir le namespace dans le fichier .cpp d'implémentation, ce qui simplifie légèrement l'écriture car on n'est pas obligé de mettre Espace:: partout devant les noms.
faudrait que je lise cette norme. C'est abordable? C'est dans le Stroustrup ou c'est autre chose? merci pour ta réponse
Le "Koenig lookup" devrait être expliqué un peu partout où on introduit les namespaces - regarde sur Google... En gros, cela veut dire que le nom d'une fonction (y compris un opérateur) n'est pas seulement recherché dans le(s) namespaces "actives" à l'endroit où se trouve l'appel (non qualifié par "NomDUnNamespace::") de cette fonction (opérateur) mais aussi dans le(s) namespace(s) de l'/des argument(s) de cet appel.
Falk
Nico R wrote:
J'aurais écrit
Le code qui suit était censé se trouver dans le fichier Foo.cpp .
Bien sûr, au début il manquait un
#include "Foo.H"
où le fichier Foo.H contient la définition de la classe Foo dans
le namespace Espace, avec les déclarations (sans définition) de
la fonction membre getA() et de la fonction "friend" operator>>() .
namespace Espace
{
int Foo::getA() { return a; }
std::istream& operator>>(std::istream& is, Foo& f) { return is >>
f.a; }
}
mais ça revient au même
merci pour ta reponse
l'assesseur n'était pas inline parce que j'en ai juste mis un dans mon
exemple pour qu'il y ait une fonction membre. par contre l'operateur
inline comme ça ça marche? parce que là en fait tu le déclares comme
une fonction membre du coup ce n'est pas vraiment une surcharge de
std::operator>>, i.e. je ne suis pas sur que je puisse l'appeler comme ça:
Espace::Foo f;
cin>>f;
Non, ces 2 fonctions ne sont pas inline - elles sont définies
en dehors de la classe Foo (et l'opérateur>> n'est même pas membre
de la classe Foo), mais à l'intérieur du namespace Espace, au niveau
du fichier Foo.cpp . Mon but était illustrer qu'on peut simplement
rouvrir le namespace dans le fichier .cpp d'implémentation, ce qui
simplifie légèrement l'écriture car on n'est pas obligé de mettre
Espace:: partout devant les noms.
faudrait que je lise cette norme. C'est abordable?
C'est dans le Stroustrup ou c'est autre chose?
merci pour ta réponse
Le "Koenig lookup" devrait être expliqué un peu partout où on
introduit les namespaces - regarde sur Google... En gros, cela
veut dire que le nom d'une fonction (y compris un opérateur)
n'est pas seulement recherché dans le(s) namespaces "actives"
à l'endroit où se trouve l'appel (non qualifié par "NomDUnNamespace::")
de cette fonction (opérateur) mais aussi dans le(s) namespace(s)
de l'/des argument(s) de cet appel.
Le code qui suit était censé se trouver dans le fichier Foo.cpp . Bien sûr, au début il manquait un #include "Foo.H" où le fichier Foo.H contient la définition de la classe Foo dans le namespace Espace, avec les déclarations (sans définition) de la fonction membre getA() et de la fonction "friend" operator>>() .
namespace Espace { int Foo::getA() { return a; } std::istream& operator>>(std::istream& is, Foo& f) { return is >> f.a; } } mais ça revient au même
merci pour ta reponse l'assesseur n'était pas inline parce que j'en ai juste mis un dans mon exemple pour qu'il y ait une fonction membre. par contre l'operateur inline comme ça ça marche? parce que là en fait tu le déclares comme une fonction membre du coup ce n'est pas vraiment une surcharge de std::operator>>, i.e. je ne suis pas sur que je puisse l'appeler comme ça:
Espace::Foo f; cin>>f;
Non, ces 2 fonctions ne sont pas inline - elles sont définies en dehors de la classe Foo (et l'opérateur>> n'est même pas membre de la classe Foo), mais à l'intérieur du namespace Espace, au niveau du fichier Foo.cpp . Mon but était illustrer qu'on peut simplement rouvrir le namespace dans le fichier .cpp d'implémentation, ce qui simplifie légèrement l'écriture car on n'est pas obligé de mettre Espace:: partout devant les noms.
faudrait que je lise cette norme. C'est abordable? C'est dans le Stroustrup ou c'est autre chose? merci pour ta réponse
Le "Koenig lookup" devrait être expliqué un peu partout où on introduit les namespaces - regarde sur Google... En gros, cela veut dire que le nom d'une fonction (y compris un opérateur) n'est pas seulement recherché dans le(s) namespaces "actives" à l'endroit où se trouve l'appel (non qualifié par "NomDUnNamespace::") de cette fonction (opérateur) mais aussi dans le(s) namespace(s) de l'/des argument(s) de cet appel.
Falk
Nico R
Non, ces 2 fonctions ne sont pas inline - elles sont définies en dehors de la classe Foo (et l'opérateur>> n'est même pas membre de la classe Foo), mais à l'intérieur du namespace Espace, au niveau du fichier Foo.cpp . Mon but était illustrer qu'on peut simplement rouvrir le namespace dans le fichier .cpp d'implémentation, ce qui simplifie légèrement l'écriture car on n'est pas obligé de mettre Espace:: partout devant les noms.
autant pour moi, j'ai répondu vite et même pas pris le temps de bien lire. merci pour la réponse en tout cas, j'y vois plus clair
amicalement
Nicolas
Non, ces 2 fonctions ne sont pas inline - elles sont définies
en dehors de la classe Foo (et l'opérateur>> n'est même pas membre
de la classe Foo), mais à l'intérieur du namespace Espace, au niveau
du fichier Foo.cpp . Mon but était illustrer qu'on peut simplement
rouvrir le namespace dans le fichier .cpp d'implémentation, ce qui
simplifie légèrement l'écriture car on n'est pas obligé de mettre
Espace:: partout devant les noms.
autant pour moi, j'ai répondu vite et même pas pris le temps de bien
lire. merci pour la réponse en tout cas, j'y vois plus clair
Non, ces 2 fonctions ne sont pas inline - elles sont définies en dehors de la classe Foo (et l'opérateur>> n'est même pas membre de la classe Foo), mais à l'intérieur du namespace Espace, au niveau du fichier Foo.cpp . Mon but était illustrer qu'on peut simplement rouvrir le namespace dans le fichier .cpp d'implémentation, ce qui simplifie légèrement l'écriture car on n'est pas obligé de mettre Espace:: partout devant les noms.
autant pour moi, j'ai répondu vite et même pas pris le temps de bien lire. merci pour la réponse en tout cas, j'y vois plus clair
amicalement
Nicolas
Loïc Joly
Nico R wrote:
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig lookup", cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les namespaces std et Espace, donc il sera trouvé dans ce dernier.
faudrait que je lise cette norme. C'est abordable?
Abordable au sens monétaire, oui (une vingtaine de $) Abordable au sens intellectuel, pourquoi pas pour un esprit tordu, mais on a fait plus palpitant comme récit...
C'est dans le Stroustrup ou c'est autre chose? merci pour ta réponse
Le Stroustrup n'est pas la norme. Mais il en reprend un certain nobre de points.
-- Loïc
Nico R wrote:
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig
lookup",
cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les
namespaces
std et Espace, donc il sera trouvé dans ce dernier.
faudrait que je lise cette norme. C'est abordable?
Abordable au sens monétaire, oui (une vingtaine de $)
Abordable au sens intellectuel, pourquoi pas pour un esprit tordu, mais
on a fait plus palpitant comme récit...
C'est dans le Stroustrup ou c'est autre chose?
merci pour ta réponse
Le Stroustrup n'est pas la norme. Mais il en reprend un certain nobre de
points.
une règle dans la Norme ("Argument-dependent name lookup" ou "Koenig lookup", cf. § 3.4.2) oblige le compilateur à chercher l'opérateur>> dans les namespaces std et Espace, donc il sera trouvé dans ce dernier.
faudrait que je lise cette norme. C'est abordable?
Abordable au sens monétaire, oui (une vingtaine de $) Abordable au sens intellectuel, pourquoi pas pour un esprit tordu, mais on a fait plus palpitant comme récit...
C'est dans le Stroustrup ou c'est autre chose? merci pour ta réponse
Le Stroustrup n'est pas la norme. Mais il en reprend un certain nobre de points.