2012-05-01 8 views
7

Sollen Funktionen in einem Namespace nicht nur über den Namespace-Scoping oder die using-Direktive erreichbar sein?Warum sind einige Funktionen in einem Namespace ohne das Namespace-Scoping-Präfix verfügbar?

Ich habe ein Problem, wo bestimmte Funktionen, die innerhalb eines Namespace definiert sind, außerhalb des Namespace zugänglich sind. Ich glaube, dass es einen Compiler-Fehler geben sollte, aber ich bekomme keinen über die drei verschiedenen Compiler, die ich versucht habe (VS.NET 2003, VS2010 und GCC 4). Hier

ist der Code:

namespace N{ 
    typedef struct _some_type *some_type; 
    struct some_struct { int x; }; 
    void A(void); 
    void B(int); 
    void C(some_type*); 
    void D(some_type); 
    void E(struct some_struct); 
} 

using N::some_type; 
using N::some_struct; 

void TestFunction() 
{ 
    some_type foo; 
    some_struct s; 

    N::A();   //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::A();   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    A();   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 

    N::B(0);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::B(0);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    B(0);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 

    N::C(&foo);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::C(&foo);  //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    C(&foo);  //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 

    N::D(foo);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::D(foo);  //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    D(foo);   //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 

    N::E(s);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::E(s);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    E(s);   //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 
} 

Keine der Funktionen sollten ohne Verwendung des N :: Präfix zugänglich sein, aber C, D und E sind aus unbekannten Gründen. Ich dachte zuerst, es wäre ein Compiler-Bug, aber weil ich das über mehrere Compiler sehe, frage ich mich, was passiert.

+0

Ich dachte, das war ein "Old-Compiler-Bug", aber das kompiliert auch auf gcc 4.6. – mfontanini

+0

Meine beste Vermutung ist die Tatsache, dass Sie diese Zeilen haben: 'mit N :: some_type;' und 'mit N :: some_struct;' und die Rückgabetypen von C, D und E sind diese Typen. – gcochard

+0

Greg, du kannst den using entfernen und es passiert immer noch. Auch die Rückgabetypen aller Funktionen sind ungültig. – syplex

Antwort

10

Ich denke, Sie sehen die Wirkung von Koenig lookup. In Ihrem Beispiel sind foo und s die im Namespace N definierten Typen . Ihre Aufrufe an die Routinen C, und E verwenden Argumente dieser Typen. Daher wird der Namensbereich N gesucht, um diese Funktionsaufrufe aufzulösen.

+3

Randnotiz: Das Hinzufügen von Klammern, d. H. '(C) (& foo)' verhindert eine argumentabhängige Suche. –

+0

Nun, Sie haben Recht. Es ist in Abschnitt 3.4.2 der 2003 C++ Spezifikation. Ich stimme diesem Teil der Spezifikation nicht zu und denke, dass es schlecht durchdacht ist, aber da ist es. Weiß jemand, ob es eine Möglichkeit gibt, ein strengeres Namespace-Scoping in GCC oder VC++ zu erzwingen? – syplex

+0

@Syplex In der Tat ist es sehr nützlich für die Suche nach freien Funktionen auf der Grundlage der Argumenttypen in Vorlagen. Ich denke nicht, dass g ++ eine solche Option bietet, da es gegen die Anforderungen des Standards gehen würde. Was ist das * echte * Problem, das du hier zu lösen versuchst? –

Verwandte Themen