c++ - que - swap en c
cómo proporcionar una función de intercambio para mi clase? (2)
¿Cuál es la forma correcta de habilitar mi swap
en algoritmos STL?
1) swap
miembro. Std std::swap
usa el truco SFINAE para usar el swap
miembros.
2) swap
permanente en el mismo espacio de nombres.
3) Especialización parcial de std::swap
.
4) Todo lo anterior.
Gracias.
EDITAR: Parece que no dije mi pregunta claramente. Básicamente, tengo una clase de plantilla y necesito algos de STL para usar el método de intercambio (eficiente) que escribí para esa clase.
1) es el uso correcto de swap
. Escríbelo de esta manera cuando escriba código de "biblioteca" y desee habilitar ADL (búsqueda dependiente de argumentos) en swap
. Además, esto no tiene nada que ver con SFINAE.
// some algorithm in your code
template<class T>
void foo(T& lhs, T& rhs){
using std::swap; // enable ''std::swap'' to be found
// if no other ''swap'' is found through ADL
// some code ...
swap(lhs, rhs); // unqualified call, uses ADL and finds a fitting ''swap''
// or falls back on ''std::swap''
// more code ...
}
2) Es la forma correcta de proporcionar una función de swap
para su clase.
namespace Foo{
class Bar{}; // dummy
void swap(Bar& lhs, Bar& rhs){
// ...
}
}
Si el swap
se usa ahora como se muestra en 1), se encontrará su función. Además, puede hacer que esa función sea un amigo si es absolutamente necesario, o proporcionar un swap
miembros llamado por la función gratuita:
// version 1
class Bar{
public:
friend void swap(Bar& lhs, Bar& rhs){
// ....
}
};
// version 2
class Bar{
public:
void swap(Bar& other){
// ...
}
};
void swap(Bar& lhs, Bar& rhs){
lhs.swap(rhs);
}
3) Te refieres a una especialización explícita. Parcial es todavía algo más y tampoco es posible para funciones, solo estructuras / clases. Como tal, dado que no puede especializar std::swap
para las clases de plantilla, debe proporcionar una función gratuita en su espacio de nombres. No es algo malo, si se me permite decirlo. Ahora, también es posible una especialización explícita, pero generalmente no desea especializar una plantilla de función :
namespace std
{ // only allowed to extend namespace std with specializations
template<> // specialization
void swap<Bar>(Bar& lhs, Bar& rhs){
// ...
}
}
4) No, ya que 1) es distinto de 2) y 3). Además, tener ambos 2) y 3) llevará a tener siempre 2) elegido, porque encaja mejor.
Para responder al EDIT, donde las clases pueden ser clases de plantilla, no necesita especialización en absoluto. considere una clase como esta:
template <class T>
struct vec3
{
T x,y,z;
};
usted puede definir clases tales como:
vec3<float> a;
vec3<double> b;
vec3<int> c;
si desea poder crear una función para implementar los 3 intercambios (no es que esta clase de ejemplo lo amerite), simplemente desea que Xeo lo diga en (2) ... sin especialización, sino que simplemente realice una función de plantilla regular:
template <class T>
void swap(vec3<T> &a, vec3<T> &b)
{
using std::swap;
swap(a.x,b.x);
swap(a.y,b.y);
swap(a.z,b.z);
}
La función de plantilla de intercambio debe estar ubicada en el mismo espacio de nombres que la clase que está tratando de intercambiar. el siguiente método encontrará y usará ese intercambio aunque no esté haciendo referencia a ese espacio de nombres con ADL:
using std::swap;
swap(a,b);