Вставка в unordered_set с пользовательской хэш-функцией - программирование
Подтвердить что ты не робот

Вставка в unordered_set с пользовательской хэш-функцией

У меня есть следующий код, чтобы сделать unordered_set<Interval>. Это прекрасно компилируется.

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;

Однако я не могу скомпилировать, когда пытаюсь вставить этот код:

  for(list<Interval>::iterator i = concat.begin(); i != concat.end(); ++i){
    test.insert((*i));
  }

Кроме того, я не могу определить, что проблема из сообщений об ошибках.

Вот пример:

note: candidate is:
note: size_t Hash::operator()(const Interval&)
note:   candidate expects 1 argument, 2 provided  

Я думал, что только один аргумент...

Кто-нибудь видит проблему с моим кодом вставки? Пожалуйста, помогите, если можете - я давно искал решение.

EDIT:

Здесь новый код создания: unordered_set<Interval, Hash> test; Тем не менее, я все еще получаю множество сообщений об ошибках. Пример:

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*’
4b9b3361

Ответ 1

Первая проблема:

Вы передаете string в качестве второго аргумента шаблона для создания экземпляра шаблона класса unordered_set<>. Второй аргумент должен быть типом вашего хешерного функтора, а std::string не является вызываемым объектом.

Возможно, нужно написать:

unordered_set<Interval, /* string */ Hash> test;
//                      ^^^^^^^^^^^^
//                      Why this?

Кроме того, я бы предложил использовать имена, отличные от begin и end для ваших (членов) переменных, так как это имена алгоритмов стандартной библиотеки С++.

Вторая проблема:

Вы должны иметь в виду что функция hasher должна быть квалифицирована как const, поэтому ваш функтор должен быть:

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());
   }
};

Третья проблема:

Наконец, если вы хотите, чтобы std::unordered_set мог работать с объектами типа Interval, вам нужно определить оператор равенства, соответствующий вашей хэш-функции. По умолчанию, если вы не укажете аргумент типа в качестве третьего параметра шаблона класса std::unordered_set, будет использоваться operator ==.

В настоящее время у вас нет перегрузки operator == для вашего класса Interval, поэтому вы должны предоставить его. Например:

inline bool operator == (Interval const& lhs, Interval const& rhs)
{
    return (lhs.b == rhs.b) && 
           (lhs.e == rhs.e) && 
           (lhs.proteinIndex == rhs.proteinIndex); 
}

Вывод:

После всех вышеуказанных изменений вы можете увидеть компиляцию кода в этом живом примере.