Atenção Mozza314
Aqui está uma simulação dos efeitos de uma std::algorithm
chamada genérica std::swap
e fazendo com que o usuário forneça sua troca no namespace std. Como se trata de um experimento, esta simulação usa em namespace exp
vez 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);
}
Para mim, isso imprime:
generic exp::swap
Se o seu compilador imprimir algo diferente, ele não está implementando corretamente a "pesquisa em duas fases" para modelos.
Se o seu compilador estiver em conformidade (com qualquer um dos C ++ 98/03/11), ele fornecerá a mesma saída que mostrei. E, nesse caso, exatamente o que você teme que aconteça, realmente acontece. E colocar seu swap
no namespace std
( exp
) não impediu que isso acontecesse.
Dave e eu somos membros do comitê e temos trabalhado nessa área do padrão por uma década (e nem sempre de acordo um com o outro). Mas essa questão foi resolvida há muito tempo, e ambos concordamos em como isso foi resolvido. Ignore a opinião / resposta de especialista de Dave nesta área por sua própria conta e risco.
Este problema veio à tona após a publicação do C ++ 98. A partir de 2001, Dave e eu começamos a trabalhar nessa área . E esta é a solução moderna:
// 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);
}
O resultado é:
swap(A, A)
Atualizar
Foi feita uma observação que:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
trabalho! Então, por que não usar isso?
Considere o caso em que seu A
é um modelo 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);
}
Agora não funciona novamente. :-(
Portanto, você pode swap
inserir o namespace std e fazê-lo funcionar. Mas você precisa se lembrar de colocar swap
no A
namespace 's para o caso quando você tem um modelo: A<T>
. E uma vez que ambos os casos irá funcionar se você colocar swap
em A
's namespace, é apenas mais fácil de lembrar (e para ensinar aos outros) para fazê-lo apenas que uma maneira.