2015-04-08 11 views
10

ho avuto un problema in un certo codice di produzione che ho ridotto al minimo al seguente test case:Cosa sta facendo la ricerca del nome in C++? (E ha ragione GCC?)

template<typename T> 
void intermediate(T t) 
{ 
    func(t); // line 4 ("func not declared in this scope") 
} 

namespace ns { 
    struct type {}; 
} 

void func(ns::type const & p); // line 11 ("declared here, later") 

void foo(ns::type exit_node) 
{ 
    intermediate(exit_node); // line 15 ("required from here") 
} 

GCC 4.5 compila questo bene. Con e senza -std=c++11, 4.7 e 4.9 produrre messaggi come:

test.cpp: In instantiation of ‘void intermediate(T) [with T = ns::type]’: 
test.cpp:15:27: required from here 
test.cpp:4:5: error: ‘func’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive] 
test.cpp:11:6: note: ‘void func(const ns::type&)’ declared here, later in the translation unit 

Tutte le seguenti tre cose farà sì che il file per compilare correttamente:

  1. Spostare func(ns::type) nella ns namespace (permettendo ADL a trovare in ns)
  2. Spostare type nel namespace globale (permettendo ADL a trovare nel ::)
  3. Sbarazzarsi della intermediate e chiamare func direttamente da foo

Quindi ... cosa sta succedendo qui? È legale per GCC respingere questo programma? Perché è func trovato dalla ricerca non qualificata nella terza variante (chiamare func direttamente da foo) ma non trovato dalla ricerca non qualificata nella variante originale nel punto di istanziazione?

+0

Dovrebbe essere: (&& è GCC a destra)? – Slava

risposta

7

La regola generale è che tutto ciò che non è nel contesto della definizione del modello può essere rilevato solo tramite ADL. In altre parole, la normale ricerca non qualificata viene eseguita solo nel contesto di definizione del modello.

Poiché nessuna dichiarazione di func è visibile quando intermediate stato definito, e func non è in uno spazio associato ns::type, il codice è mal formata.

+0

Quindi, in altre parole, gli obiettivi di call call sono l'unione di (i) quelli trovati dalla ricerca non qualificata al punto di definizione (da qui la nota "definita successivamente") e (ii) quelli trovati da ADL nel punto di istanziazione? – EvanED

+0

@ ADL EVITA considera sia la definizione che i contesti di istanziazione. –

3

GCC ha ragione. func può essere trovato solo tramite ADL poiché è una chiamata di funzione dipendente non qualificata. func viene dichiarato nello spazio dei nomi globale ma è non uno spazio dei nomi associato di ns::type, solo ns è (motivo per cui il codice corrente non riesce). Quando si sostituisce intermediate(exit_node) con una chiamata diretta a func(exit_node) all'interno di foo, quindi viene trovato dalla normale ricerca non qualificata.

Problemi correlati