tous. J'ai donc créé une classe de base comparable (a la Java) qui fait le travail de surcharger les opérateurs de comparaison en C++. Le voici:std :: map ne supprime pas les doublons avec l'objet personnalisé
template <class T>
class Comparable {
public:
bool operator== (const T& rhs) const { return this->compare(rhs) == 0; }
bool operator!= (const T& rhs) const { return !(*this == rhs); }
bool operator< (const T& rhs) const { return this->compare(rhs) < 0; }
bool operator<= (const T& rhs) const { return (*this == rhs) || (*this < rhs); }
bool operator> (const T& rhs) const { return this->compare(rhs) > 0; }
bool operator>= (const T& rhs) const { return (*this == rhs) || (*this > rhs); }
protected:
virtual int compare (const T& rhs) const = 0;
};
Les objets de la sous-classe ont à la fois un ID et des données qui doivent être une clé pour le tri. J'ai implémenté chacun pour que les objets avec le même ID retournent 0, et s'ils ne sont pas le même ID, ils trient en fonction de leurs données. Voici un exemple:
int Foo::compare(const Foo& rhs) const
{
if (_id == rhs._id)
return 0;
// _value is integer data; comparison should sort on this
if (_value == rhs._value)
{
// OK, same data, now sort on ID's
return _id.compare(rhs._id);
}
// Sort on value
return _value - rhs._value;
}
Jusqu'ici, tout va bien, je pense.
Cependant, lorsque je tente de stocker des objets Foo dans un conteneur std :: set, l'ensemble n'éliminera PAS les doublons. Autrement dit, il y aura toujours des objets qui contiennent le même ID, même si cela doit être considéré comme égal.
Quelqu'un a-t-il une idée de ce qui se passe?
EDIT: Il y a beaucoup de questions sur la raison pour laquelle le code est conçu de cette façon.
Il y a deux conditions que je dois satisfaire:
- objets avec le même ID doit être l'objet « même », quelle que soit la valeur.
- Les objets qui n'ont pas le même ID doivent être triés en fonction de leur valeur (cette valeur dépend du type de l'objet).
Cela est dû au fait que les données qui créent ces objets proviennent d'une source non vérifiée. Si cette source donne des données avec le même ID mais une valeur différente, c'est une donnée invalide.
EDIT 2: En ce qui concerne la commande stricte faible pour std :: map. Disons que vous avez deux objets Foo, A et B.
Si leurs ID sont égaux, alors A < B est faux, et B < A est faux. Si leur carte d'identité de ne sont pas égaux, alors A < B est vrai ou faux en fonction de leurs valeurs, et B < A est à l'opposé de A < B.
Si cela ne satisfait pas aux règles de classement strictes?
Dans tous les cas, si std :: set utilise l'opérateur less-than (comme c'est le cas par défaut), ne devrait-il pas fonctionner comme prévu?
EDIT 3: std::set
, et non std::map
. C'était vraiment stupide de ma part. Excuses.
Il manque un destructeur virtuel à votre classe de base. – chris
if (_id == rhs._id) return 0; Cela semble étrange - cela signifierait qu'il est égal indépendamment de la valeur, mais vous gérez l'ID de comparaison plus tard si les 'valeur's sont égaux. Laquelle est-ce? – Joe
En outre, comment cela différencie-t-il entre les données qui sont le même ID mais des valeurs différentes par rapport aux données qui ont des ID différents à partir du tri? Votre fonction est ambiguë à cet égard (je pense, vous ne montrez pas _id.compare) en ce que 2 éléments avec le même ID dont la valeur diffère de 2, et 2 éléments dont l'ID qui diffère de 2 seront traités comme égaux. – Joe