Search code examples
c++priority-queue

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.


Solution

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