Syntax for finding structures in multisets - C ++

I cannot understand the syntax for finding structures in containers.

I have a multitude of structures Event

. I am trying to find one of these structures by searching for its key. I am getting below compiler error.

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

      

I have tried several permutations to no avail. I thought that defining the conditional equality operator would be sufficient.


Decision

After correcting my typo (sorry) I now have a solution closest to AraK, added by Soapbox, suggesting to use 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) ) ); 

      

I recently discovered that another option would be to use the find_if

one discussed here .

Thanks for the help.

+2


a source to share


3 answers


You don't have a suitable constructor that takes double

. Just add the following constructor:

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

      



This is what the event looks like:

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

      

+3


a source


Apart from the missing constructor, you don't want to call find()

on the iterator ceItr

, but on currentEvents

:

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

      



Note that find()

only gives you an iterator for the first match, use equal_range()

to get the range of all matches:

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
}

      

+2


a source


You seem to have multiplayer and multifipe. Multiset is when the key and value are the same. Multimap is when key and value are related, but not the same object.

In this case, the event is not actually the key. It seems that the key "time" is the key. Since key and value are not exactly the same, you must use multimap. Using an event, since both the key and the value are meaningless here.

You don’t want to create an event with extra fields, you don’t have to just search for a given value. Instead, multimap allows you to search with double, which is what you really need. It also eliminates the need for fewer statements in the Event class.

Then your code will look something like this:

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
} 

      

0


a source







All Articles