7

Si consideri il seguente codice:Perché utilizzare l'operatore di risoluzione dell'ambito cambia quale modello sovraccarico nello spazio dei nomi globale viene chiamato?

#include <iostream> 

template <class W, class T> 
void foo(W& a, T& t) 
{ 
    std::cout << "generic" << std::endl; 
} 

template <template <bool> class W, class T> 
void foo(W<true>& a, const T& t) 
{ 
    foo(a, const_cast<T&>(t)); 
} 

template <class W> 
void foo(W& a, int& t) 
{ 
    std::cout << "int" << std::endl; 
} 

template <bool> struct what; 
template<> struct what<true> { }; 

int main() { 
    const int ci = 10; 
    what<true> wt; 

    foo(wt, ci); 

    return 0; 
} 

l'uscita è (ideone link):

int 

Questo ha senso per me: foo(what<true>&, const int&) partite del sovraccarico const_cast, che poi chiama foo(what<true>&, int&), che corrisponde al int di sovraccarico .

Eppure, se cambio la funzione const_cast al seguente:

template <template <bool> class W, class T> 
void foo(W<true>& a, const T& t) 
{ 
    ::foo(a, const_cast<T&>(t)); 
} 

L'uscita è ora (ideone link):

generic 

Questo non ha senso per me. Perché la modifica del sovraccarico di const_cast di foo per chiamare ::foo causa il richiamo della versione generica anziché della versione int?

La mia comprensione di :: è che era solo per disambiguare quale funzione chiamare nel caso in cui si abbia un metodo o una funzione nello spazio dei nomi globale. Il sovraccarico const_cast corrisponde ancora, che dovrebbe quindi chiamare ::foo(what<true>&, int&), che dovrebbe corrispondere alla specializzazione int - non dovrebbe?

Inoltre, se cambio l'ordine e posizionare il sovraccarico const_cast utilizzando ::foo dopo la int specializzazione, poi la specializzazione int viene chiamato (ideone link). Perché l'ordine di definizione è importante qui?

risposta

4

I nomi dichiarati dopo il modello possono essere trovati solo tramite ricerca nome dipendente da argomento . Il sovraccarico di int& per int& viene rilevato solo perché uno dei tipi coinvolti, W<true>, è una specializzazione di un modello di classe dichiarato nello spazio dei nomi globale. Quindi ADL cerca le dichiarazioni nello spazio dei nomi globale nel contesto dell'istanziazione e trova il sovraccarico (più specializzato) desiderato.

::foo è un id qualificato, che sopprime l'ADL, quindi vengono considerati solo i nomi dichiarati nel contesto di definizione.

Problemi correlati