2012-12-16 14 views
6

Secondo 7.3.1.2 definizioni di membri dello spazio dei nomi in C++ standard ISO/IEC 14882: 2003 (E)C++ Dichiarazione di andata e amicizia in Namespace

Ogni nome dichiarata in uno spazio dei nomi è un membro di quella namespace . Se una dichiarazione di amicizia in una classe non locale prima dichiara una classe o una funzione (ciò implica che il nome della classe o la funzione non è qualificata) la classe o la funzione di amica è un membro di lo spazio dei nomi che racchiude più interno.

// Assume f and g have not yet been defined. 
void h(int); 
template <class T> void f2(T); 
namespace A { 
    class X { 
    friend void f(X); // A::f(X) is a friend 
     class Y { 
     friend void g(); // A::g is a friend 
     friend void h(int); // A::h is a friend 
     // ::h not considered 
     friend void f2<>(int); // ::f2<>(int) is a friend 
     }; 
    }; 
    // A::f, A::g and A::h are not visible here 
    X x; 
    void g() { f(x); } // definition of A::g 
    void f(X) { /* ... */} // definition of A::f 
    void h(int) { /* ... */ } // definition of A::h 
    // A::f, A::g and A::h are visible here and known to be friends 
} 

Dal void h(int); viene prima dichiarata nel namespace globale, si tratta di un membro del namespace globale. Perché la dichiarazione di amico friend void h(int); in class Y considera A::h anziché ::h?

+0

Stai solo dichiarando un amico vuoto sulla classe X. Se avesse fatto qualcos'altro sarei preoccupato. void h (int) Dichiarato prima è nel globale ma Y è chiaramente nello spazio dei nomi A. – Jay

risposta

2

Alla fine del paragrafo si afferma:

Quando alla ricerca di una dichiarazione preliminare di una classe o di una funzione dichiarata come un amico, e quando il nome della classe amico o la funzione non è né un nome qualificato o un id-modello, gli ambiti al di fuori del namespace più interno non vengono considerati.

Questo è il motivo per cui ::h non viene considerato: non è né un nome qualificato né un modello-id. Questo è anche il motivo per cui viene considerato ':: f2`, perché è un id-modello.

1

Penso che le dichiarazioni interne ombreggiano quelle nel namespace globale. Inoltre, le dichiarazioni degli amici sono dichiarazioni in avanti, quindi ombreggiano quelle nel namespace globale e non si limitano a "riferirsi" a tali funzioni.

riferimento alla 3.3.10.1 "Nome nascondiglio" in N3485:

Un nome può essere nascosta da una dichiarazione esplicita di quello stesso nome in una regione dichiarativa annidata o classe derivata (10.2).

11.3.4 Amici:

Una funzione prima dichiarata in una dichiarazione amico ha linkage esterno (3.5). Altrimenti, la funzione mantiene il suo precedente collegamento (7.1.1).

cercando in 3.5.2:

Quando un nome ha linkage esterno, l'entità denota può essere cui da nomi da ambiti di altre unità di traduzione o da altri scopi della stessa unità di traduzione.