2009-07-16 9 views
7

Je ne comprends pas pourquoi ce morceau de code ne compile pas:Namespace Clashing en C++

namespace A { 
     class F {};    // line 2 
     class H : public F {}; 
} 

namespace B { 
     void F(A::H x);   // line 7 
     void G(A::H x) { 
       F(x);   // line 9 
     } 
} 

J'utilise gcc 4.3.3, et l'erreur est:

s3.cpp: In function ‘void B::G(A::H)’: 
s3.cpp:2: error: ‘class A::F’ is not a function, 
s3.cpp:7: error: conflict with ‘void B::F(A::H)’ 
s3.cpp:9: error: in call to ‘F’ 

Je pense que parce que, dans la ligne 9 il n'y a pas de préfixe d'espace de nommage, F(x) devrait signifier définitivement seulement B::F(x). Le compilateur essaie de lancer x dans sa propre super-classe. À ma connaissance, cela ne devrait pas être le cas. Pourquoi ça fait ça?

Répondre

11

C'est parce que compilateur fonction de recherche dans le même espace de ses arguments. Le compilateur a trouvé l'identificateur A::F mais ce n'est pas une fonction. En résultat, vous obtiendrez l'erreur.

C'est un comportement standard pour autant que je me souvienne.

3.4.2 nom dépendant de l'argument de recherche Lorsqu'un nom non qualifié est utilisé comme postfix-expression dans un appel de fonction (5.2.2), d'autres espaces de noms ne sont pas considérées lors de la recherche (3,4 non qualifiée habituelle. 1) peut être recherché, et des déclarations de fonction d'ami de l'espace de noms (11.4) non visibles autrement peuvent être trouvées. Ces modifications de la recherche dépendent des types d'arguments (et pour les arguments de modèle de modèle, l'espace de noms de l'argument modèle).

Pour chaque type d'argument T dans l'appel de fonction, il y a un ensemble de zéro ou plusieurs espaces de noms associés et un ensemble de zéro ou plusieurs classes associées à considérer. Les ensembles d'espaces de noms et de classes sont entièrement déterminés par les types des arguments de la fonction (et l'espace de noms de tout argument de modèle de modèle). Les noms de type typedef et les déclarations d'utilisation utilisés pour spécifier les types ne contribuent pas à cet ensemble. Les ensembles de namespaces et les classes sont déterminées de la façon suivante ...

Cette règle vous permet d'écrire le code suivant:

std::vector<int> x; 
// adding some data to x 
//... 

// now sort it 
sort(x.begin(), x.end()); // no need to write std::sort 

Et enfin: En raison de Core Issue 218 certains compilateurs compileraient la code en question sans aucune erreur.

+1

Ce que l'on appelle la consultation de Koenig, en fait, décrit dans la section 3.4.2 de la norme C++. –

+0

Ensuite, si VS compile ceci, c'est un bug? – liori

+0

Pourriez-vous trouver une référence à cette déclaration? Je n'ai jamais entendu parler d'une telle règle ... – xtofl

4

Avez-vous essayé d'utiliser d'autres compilateurs encore? Il y a un gcc bug report ici qui est suspendu (peu importe ce que cela signifie).

EDIT: Après quelques recherches, j'ai trouvé ce more official bug.

+0

Ceci est un exemple minimal de mon propre code qui compile sur le VS2005 de mon ami. Je n'ai pas testé cette pièce exacte cependant. Et ... DeusAduro semble n'avoir aucun problème à le compiler sur VS2005. – liori

+0

Le rapport de bug ressemble à ceci, bien qu'il implique des modèles, qui ont un schéma de recherche différent (biphasé). – xtofl

+0

Remarque: d'autres indiquent VS2005 pour compiler ce code comme prévu. J'ai essayé Essai de Comeau -> succès. Seul gcc semble souffrir de cela, semble-t-il. – xtofl

1

Très étrange, je copié et collé directement à VS 2005 et je reçois une erreur, que je pensais:

Erreur 1 erreur LNK2001: symbole externe non résolu « void __cdecl B :: F (classe A :: H) »

Parce que nous avons pas réellement défini F (x) dans l'espace de noms B ... ne sais pas pourquoi gcc donne cette erreur.

0

Je viens d'essayer de compiler sur Visual Studio 2005 et il a bien fonctionné. Je me demande si c'est une implémentation cassée de Argument Dependent Lookup où l'espace de noms des arguments a été accidentellement introduit?

Questions connexes