Ich habe zwei Snippets für ADL zu Demozwecken. Beide Snippets wurden von VC10, gcc & Comeau C++ - Compiler kompiliert, und das Ergebnis ist das gleiche für alle drei.Warum hat ADL Vorrang vor einer Funktion in 'std namespace', ist aber in einem benutzerdefinierten Namespace gleich?
< 1> ADL gegen ein benutzerdefinierten Namespace-Richtlinie:
#include <algorithm>
namespace N
{
struct T {};
void swap(T,T) {}
}
namespace M
{
void swap(N::T,N::T) {}
}
int main()
{
using M::swap;
N::T o1,o2;
swap(o1,o2);
}
Compile Ergebnis:
error C2668: 'M::swap' : ambiguous call to overloaded function
could be 'void M::swap(N::T,N::T)'
or 'void N::swap(N::T,N::T)' [found using argument-dependent lookup]
nimmt Dies wird erwartet, da ADL nicht Vorrang gegenüber normalen Ergebnis-Lookup plus ADL ist kein Bürger der 2. Klasse, das ADL-Suchergebnis ist mit normalem (nicht ADL-) unerlaubtem Lookup identisch. Deshalb haben wir die Zweideutigkeit.
< 2> ADL gegen std-Namespace-Richtlinie:
#include <algorithm>
namespace N
{
struct T {};
void swap(T,T) {} //point 1
}
namespace M
{
void swap(N::T,N::T) {}
}
int main()
{
using std::swap;
N::T o1,o2;
swap(o1,o2);
}
Dieses stellt ok.
Das Ergebnis ist Compiler wählen Sie ADL Ergebnis (es wird Präzedenzfall von Std :: Swap), dh N::swap()
bei 'Punkt 1' wird aufgerufen. Nur wenn in der Abwesenheit von "Punkt 1" (sagen wir, wenn ich diese Zeile auskommentiere), wird die Kompilierung stattdessen den Fall std::swap
verwenden.
Hinweis: Dieser Weg wurde an vielen Stellen verwendet, um die std::swap
zu überschreiben. Aber meine Frage ist, warum hat ADL Vorrang vor 'std namespace' (case2) aber wird als benutzerdefiniert namespace Funktion (case1) gleich betrachtet?
Gibt es einen Absatz im C++ - Standard, der das sagt?
============================================== =============================== Bearbeiten nach dem Lesen nützlicher Antworten, könnte für andere hilfreich sein.
Also habe ich mein Snippet 1 & optimiert jetzt ist die Ambiguität verschwunden und kompilieren anscheinend Nontemplate-Funktion, wenn Überauflösung zu tun!
#include <algorithm>
namespace N
{
struct T {};
void swap(T,T) {}
}
namespace M
{
template<class T>
void swap(N::T,N::T) {}
}
int main()
{
using M::swap;
N::T o1,o2;
swap(o1,o2); //here compiler choose N::swap()
}
Ich habe auch mein Schnipsel 2 optimiert. Nur um die Mehrdeutigkeit nur zum Spaß erscheinen zu lassen!
#include <algorithm>
namespace N
{
struct T {};
template<class _Ty> inline
void swap(_Ty& _Left, _Ty& _Right)
{
_Ty _Tmp = _Move(_Left);
_Left = _Move(_Right);
_Right = _Move(_Tmp);
}
}
namespace M
{
void swap(N::T,N::T) {}
}
int main()
{
using std::swap;
N::T o1,o2;
swap(o1,o2);
}
gcc und comeau beide sagen Mehrdeutigkeit wie erwartet:
"std::swap" matches the argument list, the choices that match are:
function template "void N::swap(_Ty &, _Ty &)"
function template "void std::swap(_Tp &, _Tp &)"
BTW VC10 dumm wie üblich lassen dies einem Durchgang in Ordnung, wenn ich die 'mit std :: Swap' entfernen.
Nur ein bisschen mehr zu schreiben: C++ Überlastung kann schwierig sein (30+ Seite in C++ Standard), aber bei appendlix B von dort eine gut lesbare 10-Seite gibt es ...
Danke für all die schönen Eingaben, jetzt ist es klar.
Der beachtenswerte Punkt ist, dass ADL zu * name lookup * gehört, und Name lookup hat keine Vorstellung von "precedence". –
@KerrekSB: Ich denke David sprach nach dem Namen Lookup-Phase, während in Überladung Auflösung, die alles über die Auswahl der besten Übereinstimmung ist. – Gob00st