Search code examples
c++inheritancepriority-queue

priority_queue top return by reference


I have the following priority_queue with items of type base. The problem is, when I get item from the Queue with top(), then call its f() function via base reference object, it does call the f of base class but not the overriden f. I want child object's f() to be called. Any help? Thanks..

    #include <queue>
    #include <iostream>

    using namespace std;

    class base {

        public:
            int id;

            virtual void f() const {

                cout << "base f()" << endl;
            }

    };

    class D1: public base {

        public:

            void f() const {

                cout << "D1 f()" << endl;
            }

    };

    class D2: public base {

        public:

            void f() const {

                cout << "D2 f()" << endl;
            }

    };

    bool operator<(const base& b1, const base& b2)
            {
        return b1.id > b2.id;
    }

    int main()
    {

        priority_queue<base, deque<base>, less<deque<base>::value_type> > Q;

        D1 d1;
        D2 d2;

        Q.push(d1);
        Q.push(d2);

// this is not something  I want
        const base& b = Q.top();
        b.f();        // base f()


// this works as I want
    const base& b2 = d2;
    b2.f();        // D1 f()

    return 0;

    }

Solution

  • Same polymorphic premise as using pointers, but here's a possible alternative using std::reference_wrapper:

    #include <functional>
    #include <queue>
    #include <iostream>
    
    using namespace std;
    
    class base {
        public:
            int id;
    
            virtual void f() const {
                cout << "base f()" << endl;
            }
    };
    
    class D1: public base {
        public:
            void f() const {
                cout << "D1 f()" << endl;
            }
    };
    
    class D2: public base {
        public:
            void f() const {
                cout << "D2 f()" << endl;
            }
    };
    
    bool operator<(const base& b1, const base& b2)
    {
        return b1.id > b2.id;
    }
    
    int main()
    {
    
        priority_queue<std::reference_wrapper<base>, deque<std::reference_wrapper<base>>, less<deque<std::reference_wrapper<base>>::value_type> > Q;
    
        D1 d1;
        D2 d2;
    
        Q.push(d1);
        Q.push(d2);
    
        // this now works as you want?
        const auto& b = Q.top();
        b.get().f();    // D1 f()
    
    
        // this works as I want
        const auto& b2 = d2;
        b2.f();        // D2 f()
    
        return 0;
    }