Rocky
Rocky

Reputation: 15

Priority queue of multiple classes C++

class Event{
public:
      enum EventType { A_1, A_2, A_3, A_4};

      Event(EvtType type = A_1, double etime = 0.0)
           : _type(type)
           , _etime(etime)
      {}

      EventType get_Type() const { return _type; };
      double get_Time() const { return _etime; }

protected:
      EventType _type;
      double _etime;
};

struct EventLess{

    bool operator()(const Event& lhs, const Event& rhs) const
        {
         return (lhs.get_Time() > rhs.get_Time());
        }
};

I can create min priority queue as below

 priority_queue<Event, std::vector<Event>, EventLess> q;

However, if I have another class like:

class Event1
{
public:
     enum EventType { disruption_1, disruption_2};

     Event(EvtType type = disruption_1, double htime = 0.0, double duration)
          : _type(type)
          , _htime(htime)
          , _duration(duration)

     {}

     EventType get_Type() const { return _type; };
     double get_Time() const { return _htime; }
     double get_Duration() const { return _duration; }

 protected:
     EventType _type;
     double _etime;
     double _duration;
 };

and I want to create the min priority queue of these two classes (Time comparing). Please anyone demonstrate me how to solve this will be thankful.


After receiving suggestion, I have improved a code by using inheritance as presented.

    #include <queue>
    #include <iostream>
    using namespace std;

    class IEvent{
    public:
        IEvent(double time_e): Etime(time_e) {}
        virtual double get_Time() const {return Etime;}
    protected:
        double Etime;

    };

    class Event1:public IEvent{
    public:
    enum EType1 { A_1, A_2, A_3, A_4};

    Event1(EType1 type1, double time_e, int _speed)
    : _type1(type1)
    , IEvent(time_e)
    , speed(_speed)
    {}

    virtual EType1 get_Type() const { return _type1; };
    virtual double get_Time() const { return Etime; }
    int get_speed() const {return speed;}

    private:
        EType1 _type1;
        int speed;
    };


    class Event2:public IEvent{
    public:
    enum EType2 { disruption_1, disruption_2};

    Event2(EType2 type2, double time_e, double duration)
    : _type2(type2)
    , IEvent(time_e)
    , _duration(duration)
    {}

    virtual EType2 get_Type() const { return _type2; };
    virtual double get_Time() const { return Etime; }
    double get_duration() const { return _duration; }

    private:
       EType2 _type2;
      double _duration;

    };

    struct IEventLess{

          bool operator()(const IEvent& lhs, const IEvent& rhs) const
          {
           return (lhs.get_Time() > rhs.get_Time());
          }
    };

    int main(){
          priority_queue<IEvent, vector<IEvent>, IEventLess> q;

          q.push(Event1(Event1::A_1, 15.0, 10));
          q.push(Event2(Event2::disruption_1, 5.0, 5.0));

          IEvent *evt;
          evt = new q.top();

          cout <<  evt.get_Type() << evt.get_Time() << endl;

}

Nevertheless, I still have some problem in calling other function in derived class, and a little bit confusing when calling top() function as show in main function.

Please anyone help me solve it out.

Thank you.

Upvotes: 0

Views: 746

Answers (2)

Richard Hodges
Richard Hodges

Reputation: 69864

boost::variant removes the need for a common base class or inheritance:

#include <queue>
#include <boost/variant.hpp>

class Event{
public:
    enum EventType { A_1, A_2, A_3, A_4};

    Event(EventType type = A_1, double etime = 0.0)
    : _type(type)
    , _etime(etime)
    {}

    EventType get_Type() const { return _type; };
    double get_Time() const { return _etime; }

protected:
    EventType _type;
    double _etime;
};

inline double get_time(const Event& e) {
    return e.get_Time();
}

class Event1
{
public:
    enum EventType { disruption_1, disruption_2};

    Event1(EventType type = disruption_1, double htime = 0.0, double duration = 0)
    : _type(type)
    , _etime(htime)
    , _duration(duration)
    {}

    EventType get_Type() const { return _type; };
    double get_Time() const { return _etime; }
    double get_Duration() const { return _duration; }

protected:
    EventType _type;
    double _etime;
    double _duration;
};

inline double get_time(const Event1& e) {
    return e.get_Time();
}


// name predicates properly
struct EventGreater{

    template<class L, class R>
    bool operator()(const L& lhs, const R& rhs) const
    {
        return get_time(lhs) > get_time(rhs);
    }
};

template<class...Ts>
double get_time(const boost::variant<Ts...>& var)
{
    return boost::apply_visitor([](auto& x) { return get_time(x); }, var);
}

struct event_handler : boost::static_visitor<void>
{
    void operator()(const Event& e) const
    {
        // handle an Event in here
    }

    void operator()(const Event1& e) const
    {
        // handle an Event1 in here
    }

};

int main()
{
    using EventVariant = boost::variant<Event, Event1>;
    // we all know that a priority queue inverts the predicate
    std::priority_queue<EventVariant, std::vector<EventVariant>, EventGreater> q;


    q.push(Event());
    q.push(Event1());

    //
    // remove an item and action it
    auto ev = std::move(q.top());
    q.pop();

    boost::apply_visitor(event_handler(), ev);
}

Upvotes: 6

lcs
lcs

Reputation: 4245

Have both Event and Event1 inherit from a common base.

class IEvent
{
public:
  virtual double get_Time() = 0;
};

class Event : public IEvent
{
public:
  virtual double get_Time() {...}
}

class Event1 : public IEvent
{
public:
  virtual double get_Time() {...}
}

You can then store the base pointers in the queue, and cast to the concrete child when needed.

std::priority_queue<std::shared_ptr<IEvent>, std::vector<IEvent>, IEventLess> q;

auto Time = q.front()->get_Time();

Upvotes: 2

Related Questions