Search code examples
c++language-lawyerpriority-queuestd

How to obtain Comparison type of priority_queue?


Most similar containers have member types like key_compare or value_compare but there none for priority_queue.

Is that because priority_queue is an adaptor? Or is this in the standard by mistake?


Solution

  • Yes, this is weird indeed and seems to be an oversight in the C++ standard. The standard declares priority_queue as:

    template <class T,
              class Container = vector<T>,
              class Compare = less<typename Container::value_type> >
    class priority_queue;
    

    And while it specifies the following public members:

    typedef typename Container::value_type value_type;
    typedef typename Container::reference reference;
    typedef typename Container::const_reference const_reference;
    typedef typename Container::size_type size_type;
    typedef Container container_type;
    

    it for some reason omits a typedef Compare value_compare; declaration. A C++ Standard Library issue for this has been submitted to the Library Working Group (LWG) by SO user Columbo.

    Workarounds

    However, you can use the following to work around the issue.

    In C++11 and later

    #include <queue>
    
    template <typename> struct GetCompare;
    
    template <typename T, typename Container, typename Compare>
    struct GetCompare<std::priority_queue<T, Container, Compare> >
    { using type = Compare; };
    
    template <typename T>
    using GetCompare_t = typename GetCompare<T>::type;
    

    For example:

    #include <type_traits>
    
    static_assert(
        std::is_same<
            GetCompare_t<std::priority_queue<int> >,
            std::less<int>
        >::value, "");
    

    In C++03 and earlier

    #include <queue>
    
    template <typename> struct GetCompare;
    
    template <typename T, typename Container, typename Compare>
    struct GetCompare<std::priority_queue<T, Container, Compare> >
    { typedef Compare type; };
    

    For example:

    int main() {
        return typename GetCompare<std::priority_queue<int> >::type()(42, 0);
    }