2012-05-01 11 views
7

Le funzioni all'interno di uno spazio dei nomi non dovrebbero essere accessibili solo utilizzando lo scope dei nomi o la direttiva using?Perché alcune funzioni all'interno di un namespace sono accessibili senza il prefisso scope dello spazio dei nomi?

Sto riscontrando un problema in cui determinate funzioni, definite all'interno di uno spazio dei nomi, sono accessibili FUORI da tale spazio dei nomi. Credo che ci dovrebbe essere un errore del compilatore, ma non ne trovo uno sui tre diversi compilatori che ho provato (VS.NET 2003, VS2010 e GCC 4).

Ecco il codice:

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! 
} 

Nessuna delle funzioni deve essere accessibile senza l'uso della N :: prefisso, ma C, D, ed E sono per qualche motivo sconosciuto. Inizialmente pensavo che si trattasse di un bug del compilatore, ma poiché lo sto vedendo su più compilatori mi fa dubitare di cosa sta succedendo.

+0

Ho pensato che si trattasse di un "bug del vecchio compilatore", ma che è stato compilato anche su gcc 4.6. – mfontanini

+0

La mia ipotesi migliore è il fatto che tu abbia queste righe: 'usando N :: some_type;' e 'usando N :: some_struct;' e i tipi di ritorno di C, D ed E sono quei tipi. – gcochard

+0

Greg, puoi rimuovere gli usi e succede ancora. Anche i tipi di restituzione di tutte le funzioni sono nulli. – syplex

risposta

10

Penso che tu stia vedendo l'effetto di Koenig lookup. Nell'esempio, foo e s sono tipi definiti nello spazio nomi N. Le chiamate alle routine C, D e E utilizzano gli argomenti di tali tipi, pertanto viene cercato lo spazio dei nomi N per risolvere tali chiamate di funzione.

+3

Nota a margine: aggiungendo parentesi, ad esempio '(C) (& foo)' impedirà la ricerca dipendente dall'argomento. –

+0

Bene, hai ragione. È nella sezione 3.4.2 delle specifiche C++ del 2003. Mi capita di non essere d'accordo con questa parte delle specifiche e penso che sia stata mal concepita, ma è così. Qualcuno sa se c'è un modo per forzare uno scope dei nomi più severo in GCC o VC++? – syplex

+0

@syplex In effetti è estremamente utile per cercare correttamente le funzioni libere basate sui tipi di argomento all'interno dei template. Non penso che g ++ offra un'opzione del genere in quanto sarebbe contraria a quanto richiesto dallo standard. Qual è il problema * reale * che stai cercando di risolvere qui? –

Problemi correlati