2010-09-09 27 views
16

Considere el siguiente fragmento:Anónimo Espacio de nombres ambigüedad

void Foo() // 1 
{ 
} 

namespace 
{ 
    void Foo() // 2 
    { 
    } 
} 

int main() 
{ 
    Foo(); // Ambiguous. 
    ::Foo(); // Calls the Foo in the global namespace (Foo #1). 

    // I'm trying to call the `Foo` that's defined in the anonymous namespace (Foo #2). 
} 

¿Cómo puedo referir a algo dentro de un espacio de nombres en el anonimato en este caso?

Respuesta

16

No puede. La norma contiene la siguiente sección (§7.3.1.1, C++ 03):

An-espacio de nombres definición sin nombre se comporta como si se sustituye por

namespace unique { /* empty body */ } 
    using namespace unique; 
    namespace unique { namespace-body } 

donde todas las ocurrencias únicas en una unidad de traducción son reemplazadas por el mismo identificador y este identificador difiere de todos los demás identificadores en todo el programa.

Por lo tanto, no tiene forma de referirse a ese nombre único.

Se puede sin embargo utilizar técnicamente algo como lo siguiente en su lugar:

int i; 

namespace helper { 
    namespace { 
     int i; 
     int j; 
    } 
} 

using namespace helper; 

void f() { 
    j++; // works 
    i++; // still ambigous 
    ::i++; // access to global namespace 
    helper::i++; // access to unnamed namespace   
} 
+0

De acuerdo, lo que dice la norma tiene sentido. Sin embargo, ¿por qué hay una ambigüedad, entonces? Si no puedo acceder al Foo en el espacio de nombres anónimo, el compilador debería poder deducir que el único otro Foo es el del alcance global. No debería tener que usar el operador de resolución de alcance en absoluto. ¿Alguna idea sobre ese aspecto del problema? – sharp02

+0

Re: su edición - Eso es más o menos lo que estoy haciendo ahora, excepto que utilizo una función de envoltura para llegar a la función objetivo real. – sharp02

+0

@sharp: hay dos símbolos 'Foo' en ese ámbito. Considere una situación equivalente: 'namespace A {int i; } espacio de nombres B {int i; } usando el espacio de nombres A; usando el espacio de nombres B; '. –

0

La única manera es poner el código que desee acceder a ese espacio de nombres dentro del propio espacio de nombres. De lo contrario, no hay manera de resolver el espacio de nombre sin nombre, ya que no tiene un identificador que pueda proporcionarle para resolver el problema de resolución ambigua.

Si su código está dentro del bloque de espacio de nombres {}, el nombre local tiene prioridad sobre el global, por lo que un Foo() llamará al Foo() dentro de su espacio de nombres, y un :: Foo() llamará el espacio de nombres en el alcance global.

4

Mientras Georg da estándar complient, correcto, derecha, y la respuesta respetable, me gustaría ofrecer mi hacky uno - utilizar otro espacio de nombres dentro del espacio de nombres en el anonimato:

#include <iostream> 

using namespace std; 

namespace 
{ 
namespace inner 
{ 
    int cout = 42; 
} 
} 

int main() 
{ 
    cout << inner::cout << endl; 
    return 0; 
} 
2

La única solución que Se puede pensar que no modifica la disposición del espacio de nombres existente es delegar main a una función en el espacio de nombres anónimo. (main sí se requiere que sea una función global (§3.6.1/1), por lo que no puede estar en un espacio de nombres en el anonimato.)

void Foo() // 1 
{ 
} 

namespace 
{ 
    void Foo() // 2 
    { 
    } 
} 

namespace { // re-open same anonymous namespace 

    int do_main() 
    { 
     Foo(); // Calls local, anonymous namespace (Foo #2). 
     ::Foo(); // Calls the Foo in the global namespace (Foo #1). 

     return 0; // return not optional 
    } 

} 

int main() { 
    return do_main(); 
} 
0

Sólo cambiar el nombre de la función de espacio de nombres local.

Cuestiones relacionadas