2011-06-15 12 views
15

¿Existe una diferencia funcional entre estos dos usos anidados de espacios de nombres sin nombre:espacios de nombres sin nombre de la jerarquización

namespace A { namespace { 
    void foo() {/*...*/} 
}} 

y

namespace { namespace A { 
    void foo() {/*...*/} 
}}} 

Por lo que veo, ambos foo s obtendrán un interno único identificador por unidad de compilación y se puede acceder con A::foo - pero ¿hay una diferencia sutil o no tan sutil que no estoy viendo?

+1

(editado) Puede ocultar efectivamente el segundo 'foo' declarando otro' A :: foo' en el nivel del archivo. El primer 'foo' siempre estará accesible como' :: A :: foo'. A menos que vuelvas a abrir 'A 'y declares allí otro' foo'. Eso es, sí, más o menos lo mismo. –

Respuesta

7

Exactamente como ha escrito, no hay diferencia.

Puede, por supuesto, agregar declaraciones en el primer nivel del espacio de nombres a los ejemplos del stand y luego será una diferencia.

namespace A { 
    int i;   // Accessed globally in this file as "A::i". 
    namespace { 
    void foo() {/*...*/} 
}} 


namespace { 
    int i;   // Accessed globally in this file simply as "i". 
    namespace A { 
    void foo() {/*...*/} 
}}} 

Tenga en cuenta que, a pesar de que el programador no tiene manera de distinguir, por el compilador, los espacios de nombres son distintos:

unnamed_namespaces.cpp:42:5: error: reference to ‘A’ is ambiguous 
unnamed_namespaces.cpp:19:17: error: candidates are: namespace A { } 
unnamed_namespaces.cpp:28:19: error:     namespace <unnamed>::A { } 

Útil:


EDIT:

Con respecto a ADL (Argumento dependiente de búsqueda de nombre), entiendo que va a haber ninguna diferencia prioridad en la resolución de sobrecarga para otra foo() de la siguiente manera:

#include <iostream> 

void foo() { std::cout << "::foo()" << std::endl; } 

namespace A { 
    namespace { 
     void foo() { std::cout << "A::<unnamed>::foo()" << std::endl; } 

     class AClass 
     { 
     public: 
      AClass() 
      { foo(); } 
     }; 
    } 
} 


namespace { 
    namespace B { 
     void foo() { std::cout << "B::<unnamed>::foo()" << std::endl; } 

     using namespace A; 

     class BClass 
     { 
     public: 
      BClass() 
      { foo(); } 

      ~BClass() 
      { A::foo(); } 
     }; 
    } 
} 

int main() 
{ 
    A::foo(); 
    B::foo(); 
    foo(); 

    A::AClass a; 
    B::BClass b; 

    return 0; 
} 

C ompiler preferirá el foo() más cercano a menos que se especifique explícitamente. Así que BClass constructor llama a B::foo() incluso teniendo un using namespace A en él. Para llamar al A::foo() en BClass destructor, la llamada debe estar explícitamente habilitada.

A::<unnamed>::foo() 
B::<unnamed>::foo() 
::foo() 
A::<unnamed>::foo() 
B::<unnamed>::foo() 
A::<unnamed>::foo() 

Tal vez se vuelven más claras si pensamos en el nombre anidados espacios de nombres y cómo se resolvió el argumento-dependiente. La diferencia principal será implícita using en los no identificados, pero no cambiará la preferencia del compilador.

+2

Creo que su ejemplo de acceso está al revés. El primero es 'A :: i' y el segundo es' i'. –

+0

Gracias Dennis. Lo corregí. – j4x

+0

Si bien esta es una excelente respuesta hasta ahora, me preguntaba qué tipo de efectos pueden tener los espacios de nombre en ADL - 'el espacio de nombres A {void bar();}' podrá encontrar 'foo()' en cualquiera de los ejemplos? – ltjax

Cuestiones relacionadas