2010-09-09 11 views
16

Si consideri il seguente frammento di codice:Anonymous Namespace ambiguità

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). 
} 

Come posso fare riferimento a qualcosa all'interno di un namespace anonimo in questo caso?

risposta

16

Non è possibile. Lo standard contiene la seguente sezione (§7.3.1.1, C++ 03):

Un anonimo-namespace definizione si comporta come se fosse sostituito da

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

dove tutte le occorrenze di univoci in un'unità di traduzione sono sostituite dallo stesso identificatore e questo identificatore differisce da tutti gli altri identificatori nell'intero programma.

Quindi non avete modo di riferirvi a quel nome univoco.

Si potrebbe tuttavia tecnicamente usare qualcosa di simile, invece il seguente:

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

Ok, quello che dice lo standard ha senso. Tuttavia, perché c'è un'ambiguità, allora? Se non riesco ad accedere a Foo nello spazio dei nomi anonimo, il compilatore dovrebbe essere in grado di dedurre che l'unico altro Foo è quello in ambito globale. Non avrei dovuto usare affatto l'operatore di risoluzione dell'oscilloscopio. Qualche idea su questo aspetto del problema? – sharp02

+0

Ri: la tua modifica - Questo è più o meno quello che sto facendo ora, tranne che uso una funzione wrapper per arrivare alla funzione obiettivo effettiva. – sharp02

+0

@sharp: ci sono due simboli 'Foo' in quell'ambito. Si consideri una situazione equivalente: 'namespace A {int i; } spazio dei nomi B {int i; } utilizzando il namespace A; usando il namespace B; '. –

0

L'unico vero modo è quello di mettere il codice che si desidera accedere a tale spazio dei nomi all'interno del namespace stesso. Non c'è modo di risolvere lo spazio dei nomi senza nome altrimenti, dato che non ha un identificatore, puoi darlo per risolvere l'ambiguo problema di risoluzione.

Se il codice è all'interno del blocco dello spazio dei nomi {} stesso, il nome locale diventa prioritario rispetto a quello globale, quindi un Foo() chiamerà Foo() all'interno del proprio spazio dei nomi e a :: Foo() chiamerà lo spazio dei nomi a portata globale.

4

Mentre Georg dà standard complient, corretto, giusto, e la risposta di tutto rispetto, vorrei offrire il mio hacky uno - utilizzare un altro spazio dei nomi all'interno del namespace anonimo:

#include <iostream> 

using namespace std; 

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

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

L'unica soluzione che si può pensare che ciò non modifichi la disposizione dello spazio dei nomi esistente è quella di delegare main a una funzione nello spazio dei nomi anonimo. (main sé è necessario per essere una funzione globale (§3.6.1/1), quindi non può essere in uno spazio dei nomi anonimo.)

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

basta rinominare la funzione di spazio dei nomi locale.