2016-03-05 10 views
8

Si consideri il seguente frammento:Dipendente ricerca dei nomi in funzione di modello: clang rifiuta, gcc accetta

struct X { }; 

namespace foo { 
    template <class T> 
    void bar() { T{} < T{}; } 

    void operator<(const X&, const X&) {} 
} 

int main() { 
    foo::bar<X>(); 
} 

clang rifiuta questo codice, gcc accetta. È un bug di gcc o è un bug clang?

+0

Non vedo come sia un errore perché il tipo "T" può riferirsi a qualsiasi tipo. Se quel tipo 'T' non sovraccarica o supporta l'operatore' <'allora la funzione' bar' fallirebbe. Dato che hai sovraccaricato l'operatore '<', va tutto bene. Immagino che tutto dipenda dal modo in cui i compilatori leggono il codice, ma la semantica non è soggetta a errori. – Poriferous

+0

@Poriferous Che non ha alcun senso. La domanda riguarda tutto il comportamento corretto di 'bar()' per tipi 'T' che non hanno' operator <'. Il comportamento corretto è: "sì, trova' bar :: operator <'" (nel qual caso, clang ha un bug) o "il codice è mal formato" (nel qual caso gcc ha un bug). – Barry

+0

Questo non ha senso perché 'bar' è una funzione e non ha un membro' operator <'. Dato che hai definito l'operatore <'per struct' X', non vedo davvero quale sia il problema qui. Anche se il sovraccarico dell'operatore fosse incorporato nella struttura 'X', il codice dovrebbe comunque essere compilato correttamente. Per essere onesti, è clang che ha il bug dal momento che sembra assumere quale sia un tipo. Voglio dire, hai provato a sostituire 'foo :: bar ()' con qualcosa come 'foo :: bar ()' e vedere se clang rifiuta anche quel codice? – Poriferous

risposta

5

GCC errato. Clang è corretto. Il fatto che GCC ingoia codice non valido come quello che hai mostrato è anche menzionato nella pagina di compatibilità di CLANG here.

I nomi non qualificati vengono cercati nei seguenti modi.

  1. Il compilatore esegue una ricerca non qualificata nell'ambito in cui è stato scritto il nome. Per un modello, ciò significa che la ricerca viene eseguita nel punto in cui è definito il modello, non dove viene istanziato. Dal momento che il operator< non è stato ancora dichiarato a questo punto, la ricerca non qualificata non lo troverà.
  2. Se il nome viene chiamato come una funzione, il compilatore esegue anche la ricerca dipendente dall'argomento (ADL). (A volte la ricerca non qualificata può sopprimere l'ADL; per ulteriori informazioni, consultare [basic.lookup.argdep] paragrafo 3.) In ADL, il compilatore esamina i tipi di tutti gli argomenti della chiamata. Quando trova un tipo di classe, cerca il nome nello spazio dei nomi di quella classe; il risultato sono tutte le dichiarazioni che trova in quegli spazi dei nomi, oltre alle dichiarazioni dalla ricerca non qualificata. Tuttavia, il compilatore non esegue ADL finché non conosce tutti i tipi di argomenti.
6

Credo che questo sia un bug gcc, archiviato come 70099. Da [temp.dep.res]:

Nella risoluzione nomi dipendenti, i nomi dalle seguenti fonti sono considerati:
(1.1) - Dichiarazioni che sono visibili al momento della definizione del modello.
(1.2) - Dichiarazioni dai namespace associati ai tipi degli argomenti della funzione sia dal contesto di istanziazione (14.6.4.1) che dal contesto di definizione.

foo::operator<() non è visibile nel punto di definizione del modello e non è in uno spazio dei nomi associato dagli argomenti della funzione (X 's associato namespace è solo lo spazio dei nomi globale ::). Quindi penso che gcc abbia torto a trovare foo::operator< e che clang sia corretto per rifiutare il codice.

Problemi correlati