proyectos - C++ igual(==) sobrecarga, acceso directo o la mejor manera de comparar todos los atributos
proyectos de programacion orientada a objetos en c++ (5)
Comenzando en C ++ 11 con la introducción de tuples también obtuvimos std::tie()
. Esto permitirá hacer una tupla de un grupo de variables y llamar a una función de comparación contra todas ellas. Puedes usarlo como
struct Foo
{
int a,b,c,d,e,f;
bool operator==(const Foo& rhs) { return std::tie(a,b,c,d,e,f) == std::tie(rhs.a,rhs.b,rhs.c,rhs.d,rhs.e,rhs.f); }
};
Aún debe enumerar todos los miembros que desea verificar, pero lo hace más fácil. También puede usar esto para hacer comparaciones mucho menores que las comparaciones.
También debe tenerse en cuenta que las variables se verifican en el orden en que las proporciona para tie
. Esto es importante por comparaciones menores y mayores que.
std::tie(a,b) < std::tie(rhs.a, rhs.b);
No tiene que ser lo mismo que
std::tie(b,a) < std::tie(rhs.b, rhs.a);
Tengo que sobrecargar un operador == en C ++ para una clase con muchos atributos.
El operador debe devolver verdadero, si y solo si todos los atributos son iguales. Un atajo podría ser útil, si estos atributos cambian con el tiempo, para evitar errores.
¿Hay un atajo para comparar cada atributo en una clase?
La única forma de hacerlo es desafortunadamente para verificar todos los atributos. Lo bueno es que si combina todos sus cheques usando &&
dejará de evaluar después de la primera declaración falsa. (evaluación de cortocircuito)
Entonces, por ejemplo, false && (4 == 4)
. El programa nunca evaluaría la parte 4 == 4
ya que todas las declaraciones combinadas por &&
deben ser true
para ser true
como resultado final. ¿Esto tiene sentido?
No es posible una solución relacionada con el operator==
. Puede generar el código relacionado desde una tabla de definición con la ayuda del llamado X-Macro . La mesa podría verse como
#define MEMBER_TBL /
/*type ,name ,default*/ /
X(int ,_(i) ,42 ) /
X(float ,_(f) ,3.14 ) /
X(std::string , t ,"Hello") /
El elemento _()
es necesario para evitar un seguimiento ,
al generar la llamada std::tie()
. Asegúrese de que el último elemento sea wo _()
. El uso para generar los miembros es:
struct Foo
{
#define _(x) x
#define X(type, name, default) type name{default};
MEMBER_TBL
#undef X
#undef _
}
Esto genera:
struct Foo
{
int i{42}; float f{3.14}; std::string t{"Hello"};
}
Para generar el operator==
puede usar:
bool operator==(Foo const& other) const {
return std::tie(
#define _(x) x,
#define X(type, name, default) this->name
MEMBER_TBL
#undef X
) == std::tie(
#define X(type, name, default) other.name
MEMBER_TBL
#undef X
#undef _
);
}
que resulta en
bool operator==(Foo const& other) const {
return std::tie(
this->i, this->f, this->t
) == std::tie(
other.i, other.f, other.t
);
}
Para agregar nuevos miembros, puede agregar simplemente una nueva entrada a la primera tabla. Todo lo demás se genera automáticamente.
Otra ventaja es que puedes agregar simplemente un método dump()
como
void print(void) const {
#define STR(x) #x
#define _(x) x
#define X(type, name, default) /
std::cout << /
STR(name) << ": " << name << " ";
MEMBER_TBL
#undef X
#undef _
#undef STR
std::cout << std::endl;
}
que resulta en
void print() const {
std::cout << "i" << ": " << i << " "; std::cout << "f" << ": " << f << " "; std::cout << "t" << ": " << t << " ";
std::cout << std::endl;
}
Toda la información relacionada con los miembros podría agregarse a la tabla en un solo lugar (punto único de información) y extraerse en otro lugar necesario.
Una Demo funcionamiento.
No hay ningún atajo. Tendrás que hacer una lista de todo.
Algunas fuentes de error se pueden reducir introduciendo una función miembro denominada tied()
como:
struct Foo {
A a;
B b;
C c;
...
private:
auto tied() const { return std::tie(a, b, c, ...); }
};
Para que su operator==
pueda usar eso:
bool operator==(Foo const& rhs) const { return tied() == rhs.tied(); }
Esto le permite solo listar a todos sus miembros una vez. Pero eso es todo. Todavía tienes que enumerarlos (por lo que aún puedes olvidar uno).
Hay una propuesta ( P0221R0 ) para crear un operator==
predeterminado operator==
, pero no sé si será aceptado.
Por el momento, no hay atajos, pero hay planes para agregar soporte para ello ( P0221R0 ).
Bjarne Stroustrup recientemente escribió una publicación en el blog sobre esto: Un poco de historia para la propuesta de comparación predeterminada
En C ++ 14, no hay nada mejor que enumerar todos los miembros y compararlos, lo que es propenso a errores. Para citar a Bjarne:
El argumento más importante para las comparaciones predeterminadas no es la conveniencia, sino el hecho de que las personas malinterpreten a sus operadores de igualdad.