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?