J'ai trouvé un comportement étrange de résolution C ++ de la surcharge de l'opérateur, je ne peux pas m'expliquer moi-même. Un pointeur à une ressource décrivant que ce serait aussi agréable qu'une réponse.
J'ai 2 unités de traduction. Dans un (appelé util.cpp / h), je déclare et définit deux opérateurs (j'espérais les implémentations réelles de lectuabilty, le problème se produit quand même): p> et: P> //test.cpp
#include "test.h"
#include "util.h"
#include <iostream>
void Namespace::SomeClass::test(std::istream& is) {
::operator>>(is, "c"); //works
is >> "c" //fails
}
3 Réponses :
:: est la portée globale, le compilateur doit donc numériser l'espace de noms global et trouver cet opérateur. est >> "C", en essayant de trouver l'opérateur >> dans l'espace de noms, donc, le compilateur trouvez-le et arrêtez la recherche, puis compilateur essayer de choisir l'opérateur avec la signature nécessaire, s'il n'y a pas de tel opérateur - compilateur échoue. Je pense que vous devriez lire Souput Herb Exceptionnel C ++. P>
Il s'agit d'un nom de cache-cache. La norme dit (C ++ 03, 3.3.7 / 1)
Un nom peut être masqué par une déclaration explicite de ce même nom dans une région déclarative imbriquée ou dérivée classe (10.2). P> blockQquote>
le "nom" sur votre cas serait
opérateur >> code> et les espaces de noms constituent des régions déclaratives imbriquées. p>
Le moyen le plus simple de résoudre ce serait à utiliser un
en utilisant code> déclaration où vous déclarez l'opérateur
<<<<<< / code>: p>
xxx pré> Notez que cette fonctionnalité ne veut pas interférer avec la recherche koenig (au moins dans votre cas, en principe, cela peut), de sorte que les opérateurs IO de
std :: code> seront toujours trouvés. p>
PS: une autre possibilité de travailler Aroud Ce numéro définirait l'opérateur de
Someclass code> comme Inline
ami code>
. De telles fonctions sont déclarées au niveau de l'espace de noms (en dehors de "leur" classe), mais ne sont pas visibles de là. Ils ne peuvent être trouvés que par Koenig Recherche. P> P>
Est-ce un concept utile? Je veux dire que je comprends bien, mais ne serait-il pas plus utile de regarder partout, si aucune signature ne va pas? (Cela ne devrait pas offenser la réponse, mais la norme C ++ :))
@hildensia a l'air de vaincre n'importe où dans le but des espaces de noms et vous courez le risque de ramasser des choses que vous n'avez jamais entendues, à cause des affrontements de nom.
@hildensia: Je ne connais pas vraiment la raison d'une telle caractéristique, mais je suppose que cela va de la tradition C de nom de nom de nom (où une variable dans une portée intérieure cache la variable de la portée extérieure), qui est en fait la droite chose à faire imho. Ensuite, vous devez envisager des problèmes tels que "si j'ai un char * a code> dans une portée intérieure et un
int a code> dans une portée extérieure, le
externe) code> être trouvé où un
int code> conviendrait? " Je pense que le processus de masquage de nom vous donne en réalité un environnement plus prévisible, par exemple. Les matchs de surcharge non parfaits ne seront pas perturbés par une personne déclarée dans la portée extérieure.
Il y a plusieurs problèmes ici; Pour commencer, vous redéfinissez un
Fonction dans l'espace de noms global qui existe déjà dans concrètement, ici: vous ne pouvez pas surcharger std :: code>. Les
Le problème que vous décrivez, cependant, est dû à la façon dont le nom de recherche fonctionne.
Fondamentalement, dans le cas de la surcharge de l'opérateur, le compilateur fait deux
Nom Recherches. Le premier (utilisé pour tous les symboles, pas seulement les opérateurs)
commence à la portée où le symbole apparaît et fonctionne vers l'extérieur: d'abord
les blocs locaux, puis la classe et ses classes de base (le cas échéant), et
Enfin, les espaces de noms, travaillant à l'espace de noms global. Un
caractéristique importante de cette recherche est qu'il s'arrête dans tout ce que
Portée Il trouve le nom: s'il trouve un nom dans la portée locale, il ne doit pas
regarde dans toutes les classes; S'il en trouve un dans une classe, il ne regarde pas dans le
classes de base ou espaces de noms, et s'il en trouve un dans un espace de noms, il
Ne regarde pas dans des espaces de noms entourant. En ce qui concerne cette recherche est
concerné, toutes les surcharges doivent être dans la même portée. La seconde recherche
affecte uniquement les fonctions et les surcharges de l'opérateur et se produit dans le contexte
des classes ou des objets utilisés comme arguments; Ainsi, si l'un des opérandes est
une classe dans la bibliothèque standard (ou quelque chose dérivé d'une classe dans le
Bibliothèque standard), le compilateur recherchera des fonctions dans
std :: code>, même
Bien que le contexte où le symbole est utilisé n'inclut pas
std :: code>.
Le problème que vous rencontrez est des types intégrés, tels que
char * code>, ne pas
implique tout espace de noms em> (pas même global): Compte tenu de vos surcharges, le premier
recherche s'arrêtera au premier opérateur
>> code> il voit et le second
seul em> regarde dans
std :: code>. Votre fonction est en ni l'un ni l'autre. Si vous voulez un
opérateur surchargé à trouver, vous devez em> le définir dans la portée de
un de ses opérandes. P>
std :: istream &
opérateur >> (std :: istream &, char *) code>, car il est déjà surchargé dans
la bibliothèque standard.
std :: istream et opérateur >> (std :: istream &, char
const *) code> est possible, mais je ne suis pas sûr de ce que c'est censé faire, car
Il ne peut pas écrire au deuxième opérande. Plus généralement, vous ne devriez que
surcharger cet opérateur pour des types que vous avez définis et que vous devriez
mettre votre surcharge dans la même espace de noms que le type lui-même, de sorte qu'il
sera trouvé par la seconde recherche ci-dessus (appelé argument dépendant
Recherche ou ADL-ou antérieur, Koenig Recherche, après la personne qui
inventé). P>
Il est en fait destiné à analyser à partir d'un flux d'entrée. où vous écrivez os << "[" << matrix << "]"; code> Vous pouvez simplement écrire
est >> "[" >> matrice >> "]"; Code >. Il est censé être un peu "Syntaxtic Suggar" dans le code hérité, je dois utiliser. Je voulais nettoyer certaines choses, pour la rendre compilée avec Clang et couru dans ce problème.
Et vous voulez une correspondance exacte, sans stocker les résultats n'importe où? Cela ressemble à un manipulateur, plus qu'un extracteur. Mais vous devriez écrire est >> match ("[") >> Matrix >> Match ("]") code> ou quelque chose de similaire. Le problème avec la façon dont vous essayez de le faire est que
opérateur >> (iStream &, char *) code> a déjà une signification définie et cette surcharge sur Const (
Char Const * Code> vs.
Char * code>) ne fera aucune fin de confusion si les surcharges font des choses totalement indépendantes. Donc, autant que j'aime la syntaxe, vous essayez d'atteindre, je ne suis pas sûr que ce soit une bonne idée.
C'est un peu déroutant, vous avez raison, mais ce n'est pas dans mon champ de changement ... mais je vais supprimer la chose non-constance, car elle n'est pas utilisée de toute façon. Il est réellement destiné à juste correspondre à partir du Istream code> et de jeter la chaîne. Si vous avez un protocole surhead, c'est un peu pratique.
Avez-vous essayé de déclarer l'espace de noms :: opérateur >> comme «inline»
BTW, il vous manque un
; code> après votre déclaration de classe
a couché le;. C'est une erreur très habituelle que je fais ...
@ Bert-jan Non, car dans ma mise en œuvre réelle, le flux d'entrée est analysé avec quelques amout de code, que je trouve beaucoup à être inlincé.