7

Betrachten Sie den folgenden Code ein:Warum ändert die Verwendung des Scope-Resolution-Operators, welche überlastete Vorlage im globalen Namespace aufgerufen wird?

#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; 
} 

Der Ausgang ist (ideone link):

int 

Das macht Sinn für mich: foo(what<true>&, const int&) entspricht der const_cast Überlastung, die dann foo(what<true>&, int&) aufruft, die die int Überlastung Spiele .

Doch wenn ich ändern, um die const_cast Funktion auf die folgenden:

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

Der Ausgang ist jetzt (ideone link):

generic 

Das macht keinen Sinn für mich. Warum bewirkt das Ändern der const_cast Überladung von foo, ::foo aufzurufen, dass die generische Version anstelle der int-Version aufgerufen wird?

Mein Verständnis von :: ist, dass es nur zu disambiguieren war, welche Funktion aufgerufen wird, wenn Sie eine Methode oder eine Funktion im globalen Namespace haben. Die Überlastung const_cast stimmt immer noch überein, die dann ::foo(what<true>&, int&) aufrufen sollte, die der int Spezialisierung entsprechen sollte - sollte es nicht?

Ferner kann, wenn ich den Auftrag und legen Sie die const_cast Überlastung mit ::foo nach der int Spezialisierung ändern, dann ist die int Spezialisierung wird aufgerufen (ideone link). Warum spielt hier die Reihenfolge der Definition eine Rolle?

Antwort

4

Namen, die nach der Vorlage deklariert wurden, können nur über gefunden werden. Argumentabhängiger Name Lookup. Ihre Überladung von foo für int& wird nur gefunden, weil einer der beteiligten Typen W<true> eine Spezialisierung einer Klassenvorlage ist, die im globalen Namespace deklariert ist. ADL sucht daher im Instanziierungskontext nach Deklarationen im globalen Namespace und findet die (spezialisiertere) gewünschte Überladung.

::foo ist eine qualifizierte ID, die ADL unterdrückt, daher werden nur im Definitionskontext deklarierte Namen berücksichtigt.