Il y a un pas vers le operator==
possible. Vous pouvez générer le code connexe à partir d'une table de définition à l'aide de ce qu'on appelle le X-Macro . Le tableau pourrait ressembler à
#define MEMBER_TBL \
/*type ,name ,default*/ \
X(int ,_(i) ,42 ) \
X(float ,_(f) ,3.14 ) \
X(std::string , t ,"Hello") \
El _()
est nécessaire pour éviter un ,
sur la génération le std::tie()
appel. Assurez-vous que le dernier élément est w.o. _()
. L'utilisation pour générer les membres est :
struct Foo
{
#define _(x) x
#define X(type, name, default) type name{default};
MEMBER_TBL
#undef X
#undef _
}
Cela génère :
struct Foo
{
int i{42}; float f{3.14}; std::string t{"Hello"};
}
Pour générer le operator==
que vous pouvez utiliser :
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 _
);
}
ce qui donne lieu à
bool operator==(Foo const& other) const {
return std::tie(
this->i, this->f, this->t
) == std::tie(
other.i, other.f, other.t
);
}
Pour ajouter de nouveaux membres, il suffit d'ajouter une nouvelle entrée à la première table. Tout le reste est généré automatiquement.
Un autre avantage est que vous pouvez ajouter simplement un dump()
méthode comme
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;
}
ce qui donne lieu à
void print() const {
std::cout << "i" << ": " << i << " "; std::cout << "f" << ": " << f << " "; std::cout << "t" << ": " << t << " ";
std::cout << std::endl;
}
Toutes les informations concernant les membres peuvent être ajoutées à la table en un seul endroit (point unique d'information) et extraites ailleurs si nécessaire.
Un travail Démo .
0 votes
Vous pouvez utiliser memcmp si votre objet est POD ou une grande partie de celui-ci POD(sur cette partie)
0 votes
Vous pouvez écrire un script (dans votre éditeur s'il le supporte. Les substitutions d'expressions régulières de Vim pourraient le faire, par exemple) pour prendre une copie des lignes de déclaration et les transformer en
element == other.element &&
8 votes
@user3545806
memcmp
ne tiendra pas compte du rembourrage, donc cela ne fonctionnera pas.0 votes
@Barry, cela fonctionnera-t-il si vous mémorisez d'abord la partie POD et ensuite utilisez memcmp ? Mais évidemment, vous avez raison, il manquait cette note dans mon commentaire.
0 votes
Ouais, mais cela nécessite que quelqu'un ait fait quelque chose d'extérieur à l'ordinateur.
operator==
donc vous ne pouvez pas garantir qu'il fera vraiment ce qu'il faut.0 votes
Certains diront que si vous avez tellement d'attributs qu'il est possible d'en oublier un, alors votre classe a trop d'attributs et devrait être divisée en classes avec moins d'attributs.
0 votes
@Barry, je suis généralement d'accord. IMHO : Il serait plus rapide en temps d'exécution mais il ne serait pas gratuit, et évidemment il ne fonctionnera pas avec aucun POD. Mais avec la conception pilotée par les données il est parfois possible de déplacer les types de POD et de les comparer séparément.
0 votes
@user3545806 vous ne pouvez pas
memcmp
plusieurs types, tels questd::string
.0 votes
@ST3 Oui c'est correct je ne peux pas memcmp std::string. Mais j'ai dit les types POD. Imaginez un objet avec 50 longs et un std::string. Je peux le diviser pour pouvoir mémoriser 50 longs et ensuite faire l'opérateur == sur la chaîne. D'un autre point de vue, le compilateur peut le faire automatiquement.
0 votes
@user3545806 Oh... Désolé, maintenant je le vois.
1 votes
@VladimirS (et @Barry) concernant
memcmp
- Je pense que c'est pire que ce que vous dites ici. Même avec POD, même si le POD est pré-initialisé (par exemple, mis à zéro), l'utilisateur peut se faire griller dans un cas particulier avec une union discriminée. Disons que l'utilisateur a une union avec un char et un int (supposons 8 bits et 32 bits), et un "tag" en dehors de l'union pour discriminer si nous devons lire le char ou l'int de l'union. Si le "char" est "actif" dans l'union par la balise, et que sémantiquement ils sont identiques, la balisememcmp
pourrait encore échouer.0 votes
@Dan Bon point. Oui, il y a des exceptions à l'utilisation de memcmp. Cependant, il y a parfois des avantages possibles. Dans l'ensemble, utilisez-le avec précaution ! Si vous n'avez pas besoin de presser des ticks supplémentaires, la réponse de Barry ci-dessous est la meilleure.