2009-07-10 10 views
6

In C++ si specifica il collegamento interno mediante il wrapping delle definizioni di classi e funzioni all'interno di uno spazio dei nomi anonimo. È anche possibile creare istanze esplicite di modelli, ma per essere standard conformi a qualsiasi istanziazione esplicita dei modelli deve verificarsi nello stesso spazio dei nomi. AFAICT questo dovrebbe compilare, ma GCC fallisce su di esso:Lo spazio dei nomi anonimo racchiude tutti gli spazi dei nomi?

namespace foo { 

template<class T> 
class bar {}; 

} 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

con l'errore:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace 'foo') 

Il che è interessante perché il namespace anonimo deve solo essere specificando il collegamento, non proprio funzionare come uno spazio dei nomi, e il namespace globale racchiude definitivamente foo, poiché racchiude ogni spazio dei nomi. Ma anche questo non funziona !:

template<class T> 
class bar {}; 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

che non riesce con lo stesso errore, appena messa in vendita di namespace globale, invece:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace '::') 

:/

+0

Quale versione di GCC - o quali opzioni del compilatore - o quale piattaforma? Ho provato il primo campione con G ++ 4.0.1 su MacOS X con e senza -Wall e si è compilato senza lamentele o avvisi. –

+0

GCC 4.2 su Solaris. –

risposta

10

Un namespace anonimo è logicamente equivalente a

namespace _TU_specific_unique_generated_name 
{ 
    // ... 
} 
using namespace _TU_specific_unique_generated_name; 

Uno spazio dei nomi, in forma anonima o in caso contrario, non ha alcun effetto sul legame dei suoi membri. In particolare, i membri di uno spazio dei nomi anonimo non ottengono magicamente il collegamento interno.

+1

Aggiungerò l'ovvio, ovvero che le cose in _TU_specific_unique_generated_name non possono essere utilizzate al di fuori del file. – Valentein

+0

In realtà è descritto in questo modo esatto nello standard, accettato. –

6

Penso che tu abbia la risposta - Gli spazi dei nomi anonimi sono spazi dei nomi distinti e unici. A proposito, il compilatore genera un numero intero casuale per rappresentare questo spazio dei nomi internamente.

0

Secondo Stroustrup (sezione 8.2.5.1) lo spazio dei nomi globale ha accesso allo spazio dei nomi anonimo (senza nome), ma non dice esplicitamente il contrario.

mi aspetto che ci si deve specificare lo spazio dei nomi con un'istruzione using o completamente qualificare riferimenti ad altri spazi dei nomi all'interno del namespace senza nome ...

7

Primo: si sta istanziare esplicitamente un modello di classe, non si sta definendo un nuovo modello di classe. Cosa

template class bar<int>; 

dice è "si prega di istanziare la barra del modello di classe per digitare int qui". Non è possibile farlo in un altro spazio dei nomi, proprio come non è possibile specializzare parzialmente un modello di classe in un altro spazio dei nomi. In particolare, il modello da istanziare esplicitamente deve essere stato definito e, nel tuo esempio, non esiste (spazio dei nomi anonimo) :: bar <>, solo foo :: bar <>.

Secondo: lo spazio dei nomi anonimo è un vero spazio dei nomi (è distinto in ogni unità di traduzione, però). Inoltre, non cambia magicamente il collegamento. Tutto dichiarato all'interno dello spazio dei nomi {} ha ancora il collegamento predefinito, proprio come in qualsiasi altro ambito di namespace. IIRC, è stato persino aggiunto per consentire l'unità di traduzione: oggetti privati, ma di collegamento esterni.

Problemi correlati