Attention Mozza314
Voici une simulation des effets d'un std::algorithm
appel générique std::swap
, et demandant à l'utilisateur de fournir son échange dans l'espace de noms std. Comme il s'agit d'une expérience, cette simulation utilise à la namespace exp
place de 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);
}
Pour moi, ceci s'imprime:
generic exp::swap
Si votre compilateur imprime quelque chose de différent, il n'implémente pas correctement la "recherche en deux phases" pour les modèles.
Si votre compilateur est conforme (à l'un des C ++ 98/03/11), alors il donnera la même sortie que je montre. Et dans ce cas, exactement ce que vous craignez se produira. Et mettre votre swap
dans namespace std
( exp
) ne l'a pas empêché de se produire.
Dave et moi sommes tous deux membres du comité et travaillons dans ce domaine de la norme depuis une décennie (et pas toujours en accord l'un avec l'autre). Mais cette question est réglée depuis longtemps et nous sommes tous les deux d'accord sur la façon dont elle a été réglée. Ne tenez pas compte de l'opinion / de la réponse d'expert de Dave dans ce domaine à vos risques et périls.
Ce problème est apparu après la publication de C ++ 98. À partir de 2001, Dave et moi avons commencé à travailler dans ce domaine . Et voici la solution moderne:
// 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);
}
La sortie est:
swap(A, A)
Mettre à jour
Une observation a été faite que:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
travaux! Alors pourquoi ne pas l'utiliser?
Considérez le cas où vous A
êtes un modèle de classe:
// 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);
}
Maintenant, cela ne fonctionne plus. :-(
Vous pouvez donc mettre swap
dans l'espace de noms std et le faire fonctionner. Mais vous devez vous rappeler de mettre swap
dans A
l'espace de nom » pour le cas où vous avez un modèle: A<T>
. Et puisque les deux cas fonctionneront si vous mettez swap
dans A
l'espace de noms », il est tout simplement plus facile à retenir (et à d' autres enseignent) à faire juste que d' une façon.