0

I would like to inherit from STL priority queue to have some additional functionality such as: allowing removal. But I am struggling to make this work when I use custom comparators. MWE:

#include <queue>

template<typename T, class Container=std::vector<T>, class Compare=std::less<typename Container::value_type>> 
class custom_priority_queue : public std::priority_queue<T, Container, Compare>
{
    public:
    // My additional functions here.
};

int main()
{
    auto pq_comp = [](const int& a, const int& b) { return a <= b; };
    std::priority_queue<int, std::vector<int>, decltype(pq_comp)> pq(pq_comp); // works
    custom_priority_queue<int> pq_custom; // works
    custom_priority_queue<int, std::vector<int>, decltype(pq_comp)> pq_custom2(pq_comp); // Error
    return 0;
}

The error is:

main.cpp: In function ‘int main()’:
main.cpp:15:87: error: no matching function for call to ‘custom_priority_queue, main():: >::custom_priority_queue(main()::&)’
   15 |     custom_priority_queue<int, std::vector<int>, decltype(pq_comp)> pq_custom2(pq_comp); // Error
      |                                                                                       ^
main.cpp:4:7: note: candidate: ‘custom_priority_queue, main():: >::custom_priority_queue(const custom_priority_queue, main():: >&)’
    4 | class custom_priority_queue : public std::priority_queue<T, Container, Compare>
      |       ^~~~~~~~~~~~~~~~~~~~~
main.cpp:4:7: note:   no known conversion for argument 1 from ‘main()::’ to ‘const custom_priority_queue, main():: >&’
main.cpp:4:7: note: candidate: ‘custom_priority_queue, main():: >::custom_priority_queue(custom_priority_queue, main():: >&&)’
main.cpp:4:7: note:   no known conversion for argument 1 from ‘main()::’ to ‘custom_priority_queue, main():: >&&’
Ahmed
  • 3
  • 2
  • your class has no constructor taking a comparator. That error is somewhat unrelated to inheriting from a std container, which perhaps wasnt a good idea to begin with. Consider that not everything has to be a member. Why don't you write a free function `remove` if thats what you want to "add" to `priority_queue` ? – 463035818_is_not_an_ai Oct 17 '22 at 12:12
  • 1
    standard library containers are not intended to be inherited from – Neil Butterworth Oct 17 '22 at 12:13
  • 1
    @463035818_is_not_a_number The class allows only `protected` access to the underlying container and that is required to implement this. – user17732522 Oct 17 '22 at 12:15
  • @NeilButterworth `std::priority_queue` specifically has protected member access to the underlying container. It seems to be designed with this use case in mind. – user17732522 Oct 17 '22 at 12:16

1 Answers1

1

Constructors are not automatically inherited, so your class probably lacks any constructor, except the implicitly-declared ones.

You can explicitly inherit all constructors of the base class:

template<typename T, class Container=std::vector<T>, class Compare=std::less<typename Container::value_type>> 
class custom_priority_queue : public std::priority_queue<T, Container, Compare>
{
    // inherit constructors
    using priority_queue::priority_queue;

    public:
    // My additional functions here.
};
user17732522
  • 53,019
  • 2
  • 56
  • 105
  • Thanks for prompt response. I had to make a small change as `using std::priority_queue::priority_queue;` and then it works. – Ahmed Oct 17 '22 at 12:30
  • @Ahmed Yes, sorry. I mixed up the two possible alternative spellings. See my edit for the simpler one that should also work here. – user17732522 Oct 17 '22 at 12:31