2010-09-02 14 views
6

Considerare questo codice:ADL e amico iniezione

template <int N> 
struct X 
{ 
friend void f(X *) {} 
}; 

int main() 
{ 
f((X<0> *)0); // Error? 
} 

compilatori sembrano essere d'accordo pesantemente. (MSVC08/10 dice no, GCC < 4.5 dice sì, ma 4.5 dice no, sun 5.1 dice sì, intel 11.1 dice sì anche se comeau dice no (entrambi sono EDG)).

Secondo "Modelli C++ - La Guida Completa":

... si presume che una chiamata che coinvolge una ricerca per gli amici a classi associate fa sì che in realtà la classe da un'istanza .. Anche se questo era chiaramente inteso da coloro che ha scritto lo standard C++, non è chiaramente enunciato nello standard.

Non sono riuscito a trovare la sezione pertinente nello standard. Qualche riferimento?

Considerate questa variante:

template <int N> 
struct X 
{ 
template <int M> 
friend void f(X<M> *) {} 
}; 

template <> 
struct X<0> 
{ 
}; 

int main() 
{ 
X<1>(); 
f((X<0> *)0); // Error? 
} 

La questione chiave qui è che scendessimo la funzione vitale iniettato da X<1> dovrebbe essere visibile durante ADL per X<0>? Sono associati? Tutti i compilatori sopra menzionati accettano questo codice, ad eccezione di Comeau che lo accetta solo in modalità rilassata. Non sono sicuro di quello che lo standard ha da dire su questo.

Cosa ne pensi?

risposta

4

Lo Standard dice alla 14.7.1/4

Un modello di classe di specializzazione è implicitamente un'istanza se il tipo di classe viene utilizzata in un contesto che richiede un tipo di oggetto completamente definito o se la completezza del tipo di classe colpisce la semantica del programma; in particolare, se un'espressione il cui tipo è una specializzazione del modello di classe è coinvolta nella risoluzione di sovraccarico, conversione puntatore, conversione puntatore a membro, la specializzazione del modello di classe è implicitamente istanziata (3.2);

noti che Vandervoorde fatto un issue report here, e la commissione ha trovato

La norma specifica già che questo crea un punto di istanziazione.

Per il secondo caso, è necessario considerare le classi e gli spazi dei nomi associati dell'argomento f(X<0>*). Questi sono, dato che questo è un puntatore a una specializzazione di template di classe (si noti che "template-id" di seguito non è del tutto corretto - C++ 0x corretto per usare il termine corretto) e anche un puntatore a una classe (questa divisione confusa è stato corretto anche in C++ 0x - elenca questi due casi in un punto elenco).

  • Se T è un modello-id, suoi namespace e classi associate sono il namespace in cui il modello è definita; [... un sacco di rumore ...]

  • Se T è un tipo di classe (inclusi i sindacati), le sue classi associate sono: la classe stessa; la classe di cui è membro, se esiste; e le sue classi di base dirette e indirette. Gli spazi dei nomi associati sono gli spazi dei nomi in cui sono definite le classi associate.

Quindi, per sintesi, abbiamo classi associate sono X<0> e gli spazi dei nomi associati sono namespace globale. Ora l'amico funzioni che sono visibili sono

  • Eventuali funzioni friend namespace-scope dichiarati nelle classi collegate sono visibili nei loro rispettivi spazi dei nomi, anche se non sono visibili nel corso di una ricerca normale

Non è stata dichiarata alcuna funzione amico in X<0>, quindi la dichiarazione della funzione amico non è visibile quando si esamina lo spazio dei nomi globale. Notare che X<0> è un tipo di classe completamente diverso rispetto a X<1>. L'istanza implicita di X<1> eseguita non ha alcun effetto su questa chiamata: aggiunge semplicemente un nome non visibile nello spazio dei nomi globale che fa riferimento a una funzione di amicizia della classe X<1>.

+0

Il primo esempio deve essere compilabile? – jpalecek

+0

Grazie :) Questo è più o meno quello che sospettavo. Come mai così tanti compilatori hanno sbagliato il secondo caso? Inoltre, lo apprezzerei se potessi fornire riferimenti nello standard anche per le altre citazioni. – uj2

+0

@ uj2 beh, almeno il clang continua a sembrare buono rispetto a GCC. Rifiuta correttamente il secondo caso. Soprattutto GCC ha un bel po 'di problemi di conformità dei modelli, quindi questo non mi sorprende. Quali sono le altre citazioni che stai cercando di trovare per i paragrafi standard? –