2010-06-14 13 views
12

Ho letto Exceptional C++ by Herb Sutter. Al raggiungimento Item 32Eccezionale C++ [Bug]?

ho trovato il seguente

namespace A 
{ 
    struct X; 
    struct Y; 
    void f(int); 
    void g(X); 
} 
namespace B 
{ 
    void f(int i) 
    { 
     f(i); // which f()? 
    } 
} 

Questo f() chiama se stessa, con ricorsione infinita. Il motivo è che l'unica f visibile() è B :: f() stesso.

C'è un'altra funzione con firma f (int), ovvero quella nel namespace A. Se B ha scritto "utilizzando il namespace A;" o "using A :: f;", quindi A :: f (int) sarebbe stato visibile come candidato durante la ricerca di f (int) e la chiamata f (i) sarebbe stata ambigua tra A :: f (int) e B :: f (int). Poiché B non ha portato A :: f (int) in ambito, tuttavia, solo B :: f (int) può essere considerato, quindi la chiamata risolve in modo univoco su B :: f (int).

Ma quando ho fatto la seguente ..

namespace A 
{ 
    struct X; 
    struct Y; 
    void f(int); 
    void g(X); 
} 
namespace B 
{ 
    using namespace A; 
    void f(int i) 
    { 
     f(i); // No error, why? 
    } 
} 

Ciò significa Herb Sutter ha sbagliato tutto? Se no, perché non ottengo un errore?

+1

Solo perché qualcosa non è un errore di compilazione non significa che deve semantica ben definita. –

+1

Ma scrivere 'usando A :: f' porta a compilare l'errore di tempo. –

+1

A seconda della versione del libro, ha fino a 11 anni. Qualsiasi modifica in C++ 03 e presto in C++ 0x non si rifletterà nei suoi esempi. (Non lo so, ma sospetto che abbia funzionato quando l'ha scritto per la prima volta.) – Bill

risposta

18

C'è una sottile differenza tra una dichiarazione using (using A::f) e una direttiva using (using namespace A).

Una dichiarazione using introduce un nome nello scope in cui viene utilizzato, pertanto using A::f effettua la chiamata a f nella definizione di B::f(int) ambigua.

A usando definizione rende i membri del namespace visibile nel campo di applicazione in cui viene utilizzato, ma appaiono come se il nome deriva dal più vicino campo di applicazione comune del namespace introdotto e lo spazio dei nomi in cui la direttiva using era Usato. Ciò significa che in questo caso lo f viene visualizzato come se fosse stato dichiarato nell'ambito globale, ma è ancora nascosto da come B::f(int).

(ISO/IEC/BS 14882:. 2003 7.3.4 [namespace.udir]/1 per tutti i drogati normali)