Atención Mozza314
Aquí hay una simulación de los efectos de una std::algorithm
llamada genérica std::swap
, y el usuario proporciona su intercambio en el espacio de nombres std. Como se trata de un experimento, esta simulación utiliza en namespace exp
lugar 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 mí esto imprime:
generic exp::swap
Si su compilador imprime algo diferente, entonces no está implementando correctamente la "búsqueda en dos fases" para las plantillas.
Si su compilador es conforme (a cualquiera de C ++ 98/03/11), entonces dará el mismo resultado que muestro. Y en ese caso, sucede exactamente lo que temes que suceda. Y poner su swap
en el espacio de nombres std
( exp
) no impidió que sucediera.
Dave y yo somos miembros del comité y hemos trabajado en esta área de la norma durante una década (y no siempre de acuerdo entre nosotros). Pero este tema se ha resuelto durante mucho tiempo y ambos estamos de acuerdo en cómo se ha resuelto. Ignore la opinión / respuesta experta de Dave en esta área bajo su propio riesgo.
Este problema salió a la luz después de la publicación de C ++ 98. Aproximadamente en 2001, Dave y yo comenzamos a trabajar en esta área . Y esta es la solución 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);
}
La salida es:
swap(A, A)
Actualizar
Se ha hecho una observación que:
namespace exp
{
template <>
void swap(A&, A&)
{
printf("exp::swap(A, A)\n");
}
}
¡trabajos! Entonces, ¿por qué no usar eso?
Considere el caso de que su A
es una plantilla de clase:
// 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);
}
Ahora no vuelve a funcionar. :-(
Entonces podría poner swap
en el espacio de nombres std y hacer que funcione. Sin embargo, usted tiene que recordar para poner swap
en A
espacio de nombres 's para el caso cuando se tiene una plantilla: A<T>
. Y dado que ambos casos funcionarán si pones swap
en A
el espacio de nombres, es más fácil recordar (y enseñar a otros) que lo hagan de una manera.