En raison de l'utilisation d'une bibliothèque dont je ne souhaite pas modifier le code, je me trouve obligé d'utiliser std :: map
.
struct compareIdentifiers { bool operator()(const Identifier& a, const Identifier& b) const { // return a < b; return true; } }; typedef std::map<Identifier, String, compareIdentifiers> IdentifierMap;
4 Réponses :
Appelez les paramètres de vos opérateurs binaires lho et tho (opérande de gauche et opérande de droite), cela rendra immédiatement clair ce que vous êtes censé retourner. (Vrai dans le cas où lho https://en.cppreference.com/w/cpp/named_req/Compare
Il est si facile d'en casser un, je viens d'apprendre à la dure.
m2c
Qu'est-ce que cela a à voir avec la question réelle ?
Il demandait quoi revenir de la comparaison. En lisant une autre réponse mieux que la mienne, je me rends compte maintenant qu'il demandait une valeur sûre à renvoyer sans faire de comparaison. Je suis content d'avoir écrit le conseil de suivre les exigences de comparaison car, comme l'ont dit d'autres personnes, retourner constamment vrai ou faux a des effets secondaires assez importants.
S'il n'y a pas de comparaison faite de toute façon, on pourrait même omettre complètement les noms pour indiquer que les paramètres ne sont en fait pas du tout utilisés (certains recommandent alors d'ajouter des noms dans les commentaires). Que vos noms proposés soient meilleurs ou non (je ne qualifierai pas, en fait, c'est assez subjectif - le premier argument se trouve à gauche, il doit donc être à gauche, de manière analogue pour la droite, donc explicite de toute façon), cela reste totalement hors de propos à la question elle-même.
Honnêtement, je ne vois pas de grandes différences entre cette réponse et celle acceptée. Au moins dans l'esprit. Quoi qu'il en soit désolé pour les ordures que j'ai écrites dans cette page.
Différence avec la réponse acceptée? Eh bien, vous ne perdez aucun mot sur les conséquences de renvoyer constamment vrai ou faux, n'est-ce pas? Mais c'est de cela qu'il s'agit. Si l'auteur utilisait les identifiants que vous proposez, la question ne changerait pas du tout, n'est-ce pas? C'est pourquoi votre réponse est sans rapport (contre exemple: il aurait été approprié que l'auteur ait mélangé les variables dans son code à cause de noms mal sélectionnés).
"Des ordures"? Vous jugez beaucoup trop strict. En effet, il est important de choisir de bons identifiants qui s’expliquent d'eux-mêmes, uniquement que cette question n'est pas le bon endroit pour le sujet - du moins si elle est isolée comme dans votre réponse. Mais ne vous découragez pas - la prochaine réponse correspondra certainement mieux ...
Toujours renvoyer true n'est pas valide. Cela signifierait (par exemple) que A et
B seraient tous les deux vrais. Cela contredit les exigences d'un comparateur
std :: map
, à savoir qu'il impose un ordre faible strict . Il est tout à fait possible que le retour de true fasse planter votre programme.
Toujours renvoyer false est valide, cela signifie effectivement que toutes les clés sont considérées comme égales. Ainsi, une seule clé pourrait être ajoutée à la carte (merci aschepler pour la correction).
Qu'est-ce qui vous empêche d'écrire un comparateur sensé?
La classe d'identifiant n'a pas d'opérateur <
Pourquoi c'est un problème? Il suffit de créer quelque chose qui satisfait un ordre strict et de le mettre dans votre comparateur. L'ordre que vous utilisez peut être complètement arbitraire,
Pourquoi ne pas simplement retourner faux? Edit: C'est un problème car c'est cher de comparer la classe ... à première vue.
@ElanHickler Juste un opérateur booléen autonome <(Identifier const & x, Identifier const & y) {return / * comparaison si nécessaire * /; }
et vous en avez un ...
alors pourquoi avons-nous 5 votes positifs pour "Toujours retourner faux est valide"? Cette réponse doit être supprimée ou rejetée.
@ElanHickler Rappelez-moi de ne pas essayer de vous aider à nouveau. Mis à part le ton ingrat, je peux voir que vous n'avez pas bien lu ma réponse (ou que vous ne l'avez pas comprise). Pour être clair, renvoyer false ne rompt aucune règle de C ++ (contrairement au retour true). En ce sens, c'est valable. Ce n'est cependant pas utile.
Je retire mon commentaire ... je n'ai pas réfléchi.
@john whaaat? Je l'ai lu parfaitement clair. Ted a dit que votre réponse était fausse, pas moi. Je ne sais pas mieux, c'est pourquoi je pose ici des questions?!?!?
@ElanHickler utilisant le return true
comparer avec std :: map
est un comportement non défini. l'utilisation du return false
compare n'est pas un comportement indéfini, mais signifie que la carte ne peut contenir au plus qu'un élément, car chaque élément potentiel se compare de la même manière que tous les autres éléments potentiels.
Merci d'avoir expliqué Caleth, maintenant je comprends. Ohhhhhhhhhhh !!!!!!!!!!!!!!!! J'ai juste eu une autre idée. Au lieu d'utiliser un unordered_map, je peux faire un comparateur de hachage comme this_hash
J'ai pu créer un hachage personnalisé pour cette classe en examinant son implémentation et ses types de retour et les types de retour de ses types de retour jusqu'à ce que je trouve une série efficace de méthodes qui retourne un type standard que je pourrais renvoyer que std :: hash
a une spécialisation spécifique au type. La liste se trouve ici: http://www.cplusplus.com/reference/functional/hash /
struct IdentifierComparator { bool operator()(const Identifier& left, const Identifier& right) const { return left.getCharPointer().getAddress() < right.getCharPointer().getAddress(); } }; typedef std::map<Identifier, String, IdentifierComparator> IdentifierMap;
Si je veux utiliser std :: map
alors je peux créer un comparateur comme celui-ci:
struct IdentifierHash { size_t operator()(const juce::Identifier& v) const { std::hash<char*> hash; return hash(v.getCharPointer().getAddress()); } }; typedef std::unordered_map<Identifier, String, IdentifierHash> IdentifierMap;
J'ai essayé d'utiliser std :: unordered_map mais j'ai obtenu une erreur:
Erreur C2280 'std :: hash <_kty> :: hash (void)': tentative de référence à une fonction supprimée
Cela est dû au fait que la carte n'est pas ordonnée utilisant une instance de
std :: hash
, mais sa spécialisation pour votre classeIdentifier
a un opérateursupprimé () . Vous avez maintenant deux options:
spécialisez
std :: hash
pour votre type:namespace std { template<> class hash { public: std::size_t operator()(Identifier const&) const { return /* whatever is appropriate */; // best is if you can base the hash code on already defined // hashes of its members } }; }écrivez votre propre classe de hachage (en fournissant à nouveau
operator ()
) et fournissez-la comme troisième paramètre de modèle à votre carte non ordonnée:std :: unordered_map
Pourquoi ne pas utiliser
std :: unordered_map
si c'est ce que vous voulez? Ou copier sur une carte non ordonnée? Quel est le problème réel que vous devez résoudre? Pourquoi avez-vous besoin de traiter lestd :: map
ordonné comme non ordonné?En ce qui concerne le message d'erreur, vous devez spécialiser
std :: hash
pour votre type de clé si vous souhaitez utiliserstd :: unordered_map
. Il existe de nombreux tutoriels et exemples partout sur Internet si vous cherchez un peu.Si vous devez renvoyer une valeur constante, cette constante ne peut pas être
true
, car elle n'est pas valide pour quecomp (x, x)
soit vrai pour n'importe quel objet. Vous pouvez toujours renvoyerfalse
, ce qui signifie que lamap
peut contenir au plus une paire clé-valeur. Ce n'est probablement pas la manière de faire ce que vous voulez faire.Pourquoi ne pas implémenter simplement une fonction de comparaison simple? Je ne sais pas ce qu'est
Identifier
, mais je parie qu'il a une représentation numérique ou chaîne qui mériterait d'appliquer un opérateur<
.J'ai finalement eu une percée mentale. Ma solution est
IdentifierA.getCharPointer (). GetAddress () La raison pour laquelle je n'ai pas fait cela avant est parce que je pensais que la seule façon de comparer les classes Indentifier était avec une méthode de comparaison de chaînes lente.