Синтаксис для поиска структур в мультимножествах - C ++ - PullRequest
2 голосов
/ 13 мая 2010

Я не могу понять синтаксис для поиска структур в контейнерах.

У меня есть мультимножество Event структур. Я пытаюсь найти одну из этих структур, ища по ее ключу. Я получаю сообщение об ошибке компилятора ниже.

struct Event {
 public:
  bool operator < ( const Event & rhs ) const {
    return ( time < rhs.time );
  }
  bool operator > ( const Event & rhs ) const {
    return ( time > rhs.time );
  }
  bool operator == ( const Event & rhs ) const {
    return ( time == rhs.time );
  }

  double time;
  int eventID;
  int hostID;
  int s; 
};

typedef std::multiset< Event, std::less< Event > > EventPQ;

EventPQ currentEvents;
double oldRecTime = 20.0;
EventPQ::iterator ceItr = currentEvents.find( EventPQ::key_type( oldRecTime ) ); // no matching function call

Я пробовал несколько перестановок, но безрезультатно. Я думал, что определения оператора условного равенства будет достаточно.


Решение

После исправления моей опечатки (извините) у меня теперь есть решение, наиболее близкое к AraK, дополненное предлагаемым Soapbox использованием explicit:

struct Event { 
   explicit Event(double t) : time(t), eventID(), hostID(), s() {}
   Event(double t, int eid, int hid, int stype) : time(t), eventID( eid ), hostID( hid ), s(stype) {}
   ... 
};

EventPQ::iterator ceItr = currentEvents.find( EventPQ::key_type( Event(oldRecTime) ) ); 

Я недавно обнаружил, что другим вариантом было бы использовать find_if, обсуждается здесь .

Спасибо за помощь.

Ответы [ 3 ]

3 голосов
/ 13 мая 2010

У вас нет подходящего конструктора, который принимает double. Просто добавьте следующий конструктор:

Event(double t) : time(t), eventID(/**/), hostIDeventID(/**/), s(/**/)
{ }

Вот как выглядит событие:

struct Event {
 public:
 // Initialize other variables as needed
 Event(double t) : time(t), eventID(/**/), hostIDeventID(/**/), s(/**/)
 { }

  bool operator < ( const Event & rhs ) const {
    return ( time < rhs.time );
  }
  bool operator > ( const Event & rhs ) const {
    return ( time > rhs.time );
  }
  bool operator == ( const Event & rhs ) const {
    return ( time == rhs.time );
  }

  double time;
  int eventID;
  int hostID;
  int s; 
};

// No need for std::less because it is used by default,
// when you define 'operator <' in your class
typedef std::multiset< Event > EventPQ;

EventPQ currentEvents;
double oldRecTime = 20.0;
// You can just pass the double, a temporary object will be created
// for you.
EventPQ::iterator ceItr = currentEvents.find( oldRecTime );
2 голосов
/ 13 мая 2010

Помимо отсутствующего конструктора, вы не хотите вызывать find() для итератора ceItr, но для currentEvents:

EventPQ::iterator ceItr = currentEvents.find(EventPQ::key_type(oldRecTime));

Обратите внимание, что find() дает вам итератор только для первого совпадения, используйте equal_range(), чтобы получить диапазон всех совпадений:

std::pair<EventPQ::iterator, EventPQ::iterator> result;
result = currentEvents.find(EventPQ::key_type(oldRecTime));

for(EventPQ::iterator it = result.first; it != result.second; ++it) {
    // do stuff
}
0 голосов
/ 13 мая 2010

Вы, кажется, перепутали мультимножество и мультикарту. Мультисеть предназначена для случаев, когда ключ и значение совпадают. Multimap - это когда ключ и значение связаны, но не один и тот же объект.

В этом случае Event не является ключом. Двойник «время» кажется ключом. Поскольку ключ и значение не совпадают, вам следует использовать мультикарту. Использование события в качестве ключа и значения здесь не имеет смысла.

Вы не хотите создавать событие с дополнительными полями, которые вам не нужны просто для поиска заданного значения. Вместо этого, мультикарта позволяет вам искать с использованием двойной, что вы действительно хотите. Это также избавляет от необходимости использовать меньше операторов в классе Event.

Ваш код будет выглядеть примерно так:

struct Event {
  double time;
  int eventID;
  int hostID;
  int s; 
};

typedef std::multimap<double, Event> EventPQ;

EventPQ currentEvents;
double oldRecTime = 20.0;
std::pair<EventPQ::iterator, EventPQ::iterator> results = currentEvents.equal_range(oldRecTime);

for(EventPQ::iterator cur = results.first; cur != results.second; ++cur) {
    // do something to *cur
} 
...