2009-07-10 15 views
6

En C++, especifica vínculos internos al incluir sus definiciones de clases y funciones dentro de un espacio de nombres anónimo. También puede crear instancias explícitas de plantillas, pero para ser estándares que cumplan cualquier instancia explícita de las plantillas debe ocurrir en el mismo espacio de nombres. AFAICT esto debe compilar, pero GCC falla en él:¿El espacio de nombre anónimo encierra todos los espacios de nombres?

namespace foo { 

template<class T> 
class bar {}; 

} 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

con el error:

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

cual es interesante debido a que el espacio de nombres en el anonimato simplemente se debe especificar la vinculación, en realidad no funciona como un espacio de nombres, y el espacio de nombre global definitivamente incluye foo, ya que incluye cada espacio de nombre. Pero incluso esto no funciona !:

template<class T> 
class bar {}; 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

Qué falla con el mismo error, simplemente hacer una lista del espacio de nombres global en su lugar:

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

:/

+0

¿Qué versión de GCC, o qué opciones de compilador, o qué plataforma? Probé la primera muestra con G ++ 4.0.1 en MacOS X con y sin -Wall y se compiló sin queja o advertencia. –

+0

GCC 4.2 en Solaris. –

Respuesta

10

Un espacio de nombres en el anonimato es lógicamente equivalente a

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

Un espacio de nombres, anónimos o no, no tiene ningún efecto sobre la vinculación de sus miembros. En particular, los miembros de un espacio de nombre anónimo no obtienen mágicamente vínculos internos.

+1

Agregaré lo obvio, que es que las cosas en _TU_specific_unique_generated_name no se pueden usar fuera del archivo. – Valentein

+0

En realidad, se describe de esta manera en el estándar, aceptado. –

6

Creo que tienes tu respuesta - los espacios de nombres anónimos son espacios de nombres distintos y únicos. Por cierto, el compilador genera un entero grande aleatorio para representar ese espacio de nombres internamente.

0

Según Stroustrup (sección 8.2.5.1), el espacio de nombres global tiene acceso al espacio de nombres anónimo (sin nombre), pero no dice explícitamente lo contrario.

espero que tendría que especificar el espacio de nombres con una instrucción using o totalmente calificar mención de otros espacios de nombres dentro del espacio de nombres sin nombre ...

7

Primero: Usted está explícitamente instanciar una plantilla de clase, no se está definiendo una nueva plantilla de clase Lo que

template class bar<int>; 

dice es "por favor instancia la barra de plantilla de clase para tipo int aquí". No puede hacer eso en otro espacio de nombre, del mismo modo que no puede especializar parcialmente una plantilla de clase en otro espacio de nombres. En particular, la plantilla para ser explícitamente instanciada debe haberse definido, y en su ejemplo, no hay (espacio de nombres anónimo) :: bar <>, solo foo :: bar <>.

Segundo: el espacio de nombres anónimo es un espacio de nombres real (sin embargo, es distinto en cada unidad de traducción). Tampoco cambia mágicamente el enlace. Todo lo declarado dentro del espacio de nombres {} todavía tiene el enlace predeterminado, al igual que en cualquier otro ámbito de espacio de nombres. IIRC, incluso se agregó para permitir la traducción de objetos de unidad privada, pero de vinculación externa.

Cuestiones relacionadas