J'ai le code suivant pour faire un unordered_set<Interval>
. Cela compile très bien.
struct Interval {
unsigned int begin;
unsigned int end;
bool updated; //true if concat. initially false
int patternIndex; //pattern index. valid for single pattern
int proteinIndex; //protein index. for retrieving the pattern
};
struct Hash {
size_t operator()(const Interval &interval);
};
size_t Hash::operator()(const Interval &interval){
string temp = to_string(interval.begin) + to_string(interval.end) + to_string(interval.proteinIndex);
return hash<string>()(temp);
}
unordered_set<Interval, string, Hash> test;
Cependant, je ne peux pas compiler lorsque j'essaie d'insérer à l'aide de ce code:
for(list<Interval>::iterator i = concat.begin(); i != concat.end(); ++i){
test.insert((*i));
}
De plus, je ne peux pas déterminer quel est le problème à partir des messages d'erreur, par exemple:
note: candidate is:
note: size_t Hash::operator()(const Interval&)
note: candidate expects 1 argument, 2 provided
Je pensais n'avoir fourni qu'un seul argument ...
Quel est le problème avec mon code d'insertion?
Voici le nouveau code d'instanciation: unordered_set<Interval, Hash> test;
Cependant, je reçois toujours une multitude de messages d'erreur, par exemple:
note: candidate is:
note: size_t Hash::operator()(const Interval&) <near match>
note: no known conversion for implicit ‘this’ parameter from ‘const Hash*’ to ‘Hash*’
Premier problème:
Vous passez string
comme deuxième argument de modèle pour votre instanciation de unordered_set<>
modèle de classe. Le deuxième argument doit être le type de votre foncteur de hachage , et std::string
n'est pas un objet appelable.
Peut-être destiné à écrire:
unordered_set<Interval, /* string */ Hash> test;
// ^^^^^^^^^^^^
// Why this?
De plus, je suggère d'utiliser des noms autres que begin
et end
pour vos variables (membres), car ce sont des noms d'algorithmes de la bibliothèque standard C++.
Deuxième problème:
Vous devez garder à l'esprit, que la fonction de hachage doit être qualifiée de const
, donc votre foncteur doit être:
struct Hash {
size_t operator() (const Interval &interval) const {
// ^^^^^
// Don't forget this!
string temp = to_string(interval.b) +
to_string(interval.e) +
to_string(interval.proteinIndex);
return (temp.length());
}
};
Troisième problème:
Enfin, si vous voulez std::unordered_set
pour pouvoir travailler avec des objets de type Interval
, vous devez définir un opérateur d'égalité cohérent avec votre fonction de hachage. Par défaut, si vous ne spécifiez aucun argument de type comme troisième paramètre du std::unordered_set
modèle de classe, operator ==
sera utilisé.
Vous n'avez actuellement aucune surcharge de operator ==
pour votre classe Interval
, vous devez donc en fournir une. Par exemple:
inline bool operator == (Interval const& lhs, Interval const& rhs)
{
return (lhs.b == rhs.b) &&
(lhs.e == rhs.e) &&
(lhs.proteinIndex == rhs.proteinIndex);
}
Conclusion:
Après toutes les modifications ci-dessus, vous pouvez voir votre code se compiler dans ce exemple en direct .
Je pense, Andy Prowl parfaitement correction des problèmes avec votre code. Cependant, j'ajouterais la fonction membre suivante à votre Interval
, qui décrit ce qui rend deux intervalles identiques:
std::string getID() const { return std::to_string(b) + " " + std::to_string(e) + " " + std::to_string(proteinIndex); }
Veuillez noter que j'ai également suivi la suggestion d'Andy Prowl et renommé les membres begin
en b
et end
en e
. Ensuite, vous pouvez facilement définir les fonctions de hachage et de comparaison en utilisant expressions lambda . Par conséquent, vous pouvez définir votre unordered_set
comme suit:
auto hash = [](const Interval& i){ return std::hash<std::string>()(i.getID()); };
auto equal = [](const Interval& i1, const Interval& i2){ return i1.getID() == i2.getID(); };
std::unordered_set<Interval, decltype(hash), decltype(equal)> test(8, hash, equal);
Enfin, pour des raisons de lisibilité, j'ai converti votre boucle for
en boucle for
basée sur une plage:
std::list<Interval> concat {{1, 2, false, 3, 4}, {2, 3, false, 4, 5}, {1, 2, true, 7, 4}};
for (auto const &i : concat)
test.insert(i);
for (auto const &i : test)
std::cout << i.b << ", " << i.e << ", " << i.updated << std::endl;
Sortie (je viens d'imprimer les trois premiers membres de chaque Interval
):
2, 3, 0
1, 2, 0
Comme vous pouvez le voir, seuls deux intervalles sont imprimés. Le troisième ({1, 2, true, 7, 4}
) n'a pas été inséré dans concat
, car ses b
, e
et proteinIndex
sont égaux à ceux du premier intervalle ({1, 2, false, 3, 4}
).