Achtung Mozza314
Hier ist eine Simulation der Auswirkungen eines generischen std::algorithm
Aufrufs std::swap
, bei der der Benutzer seinen Swap im Namespace std bereitstellt. Da dies ein Experiment ist, verwendet diese Simulation namespace exp
anstelle von namespace std
.
// simulate <algorithm>
#include <cstdio>
namespace exp
{
template <class T>
void
swap(T& x, T& y)
{
printf("generic exp::swap\n");
T tmp = x;
x = y;
y = tmp;
}
template <class T>
void algorithm(T* begin, T* end)
{
if (end-begin >= 2)
exp::swap(begin[0], begin[1]);
}
}
// simulate user code which includes <algorithm>
struct A
{
};
namespace exp
{
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
// exercise simulation
int main()
{
A a[2];
exp::algorithm(a, a+2);
}
Für mich druckt dies aus:
generic exp::swap
Wenn Ihr Compiler etwas anderes druckt, implementiert er die "Zwei-Phasen-Suche" für Vorlagen nicht korrekt.
Wenn Ihr Compiler konform ist (mit C ++ 98/03/11), gibt er dieselbe Ausgabe aus, die ich zeige. Und in diesem Fall passiert genau das, was Sie befürchten. Und das Einfügen Ihres swap
Namespace std
( exp
) hat dies nicht verhindert.
Dave und ich sind beide Komiteemitglieder und arbeiten seit einem Jahrzehnt in diesem Bereich des Standards (und sind uns nicht immer einig). Dieses Problem ist jedoch schon lange gelöst, und wir sind uns beide einig, wie es gelöst wurde. Ignorieren Sie Daves Expertenmeinung / Antwort in diesem Bereich auf eigene Gefahr.
Dieses Problem trat nach der Veröffentlichung von C ++ 98 auf. Ab ungefähr 2001 begannen Dave und ich, diesen Bereich zu bearbeiten . Und das ist die moderne Lösung:
// simulate <algorithm>
#include <cstdio>
namespace exp
{
template <class T>
void
swap(T& x, T& y)
{
printf("generic exp::swap\n");
T tmp = x;
x = y;
y = tmp;
}
template <class T>
void algorithm(T* begin, T* end)
{
if (end-begin >= 2)
swap(begin[0], begin[1]);
}
}
// simulate user code which includes <algorithm>
struct A
{
};
void swap(A&, A&)
{
printf("swap(A, A)\n");
}
// exercise simulation
int main()
{
A a[2];
exp::algorithm(a, a+2);
}
Ausgabe ist:
swap(A, A)
Aktualisieren
Es wurde festgestellt, dass:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
funktioniert! Warum also nicht das benutzen?
Stellen Sie sich den Fall vor, dass es sich bei Ihrer A
Klasse um eine Klassenvorlage handelt:
// simulate user code which includes <algorithm>
template <class T>
struct A
{
};
namespace exp
{
template <class T>
void swap(A<T>&, A<T>&)
{
printf("exp::swap(A, A)\n");
}
}
// exercise simulation
int main()
{
A<int> a[2];
exp::algorithm(a, a+2);
}
Jetzt funktioniert es nicht mehr. :-(
Sie können also den swap
Namespace std eingeben und es funktionieren lassen. Aber Sie müssen sich daran zu erinnern setzen swap
in A
‚s - Namensraum für den Fall , wenn Sie eine Vorlage haben: A<T>
. Und da beiden Fälle werden funktionieren , wenn Sie setzen swap
in A
‚s - Namensraum ist es einfach leichter zu merken (und zu lehren andere) zu tun es einfach , dass ein Weg.