2011-02-03 10 views
22

Ho qui un piccolo pezzo di codice per la tua considerazione che mi lascia un po 'imbarazzato. La cosa strana è che si compila sia su Sun Studio che su GCC anche se penso che non dovrebbe.Le funzioni con argomenti di classe sono trapelate da uno spazio dei nomi?

Considerate questo:

namespace name 
{ 
    class C 
    { 
     int a; 
    }; 

    void f(C c); 
    void g(int a); 
} 

int main(int argc, char** argv) 
{ 
    name::C c; 

    name::f(c); 
    f(c); // <--- this compiles, strangely enough 

    name::g(42); 
    // g(42); <--- this does not, as I expected 
} 

L'argomento di classe dallo stesso namespace provoca la funzione f a 'fuga' fuori dello spazio dei nomi ed essere accessibili senza name::.

Qualcuno ha una spiegazione per questo? Sono certamente io e non il compilatore a sbagliare qui.

+0

Interessante, BTW compilatore intel (ICPC) compila questo pure ... – Artyom

+0

modificato la mia domanda proprio al fine di rimuovere i bit irrilevanti e rendere più facile da trovare per gli altri con lo stesso problema. – lytenyn

risposta

28

Si chiama argument-dependent lookup (o Koenig lookup). In breve, il compilatore cercherà la funzione in namespace che sono gli spazi dei nomi dei tipi di argomenti.

+1

Grazie, questa è una funzionalità in C++ di cui non avevo mai sentito parlare .. – lytenyn

+5

@lytenyn: è quella che usi tutti i giorni però :) 'std :: string s; s + = "aa"; ', qui' + = 'deriva dallo spazio dei nomi' std' anche se non lo hai mai specificato, grazie ad ADL. –

+0

@ matthieu-m: hai perfettamente ragione, ovviamente, la stessa cosa quando usi iostreams. Ma queste sono le piccole cose a cui non penserai mai a meno che qualcuno non ti prenda il naso :) Inoltre, non riesco a ricordare nessun libro C++ che abbia mai letto, anche se è così fondamentale. Questo potrebbe essere solo il mio ricordo, ovviamente. – lytenyn

11

Questo è Argument-Dependent Name Lookup, a.k.a. ADL, a.k.a. Ricerca di Koenig. Questo è stato inventato per rendere gli operatori di lavoro come previsto, ad esempio:

namespace fu { 
    struct bar { int i; }; 
    inline std::ostream& operator<<(std::ostream& o, const bar& b) { 
     return o << "fu::bar " << b.i; 
    } 
} 

fu::bar b; 
b.i = 42; 
std::cout << b << std::endl; // works via ADL magic 

Senza ADL dovreste o portare esplicitamente l'operatore di output con brutto using fu::operator<<;, o utilizzare chiamata ancora più brutto esplicito:

fu::operator<<(std::cout, b) << std::endl; 
+1

+1 per il link, vorrei aver riassunto l'articolo però. – Crisfole

+2

L'articolo è molto breve, dov'è la tua curiosità? –

6

È dovuto alla "ricerca dipendente dall'argomento". La rimozione di const non cambierà il comportamento che stai vedendo. Per dimostrare che si tratta di ADL, provare a spostare il St struct al di fuori dello spazio dei nomi ...

struct St 
{ 
    int a; 
}; 

namespace name 
{ 
    void f(const St& st); 
    void g(int a); 
} 

int main(int argc, char** argv) 
{ 
    St st; 

    name::f(st); 
    f(st); // <--- now you will get the expected compile error 

    name::g(42); 
    // g(42); <--- this does not, as I expected 
} 
1

che è causata da argomento di ricerca dipendente.

Problemi correlati