Search code examples
c++templatesstlstdpriority-queue

Priority Queue With a Custom Comparator No Matching Constructor


I am trying to create a priority queue with a custom comparator but the following code gives me a compile error:

    auto comparator = [](std::pair<std::vector<int>, File&> const &a, std::pair<std::vector<int>, File&> const &b) {
      return a.first.front() > b.first.front();  
};

     std::priority_queue<std::pair<std::vector<uint64_t>, File&>,
      std::vector<std::pair<std::vector<uint64_t>, File&>>,
      decltype(comparator)> pq;

This is the error I am getting:

In template: no matching constructor for initialization of 'std::priority_queue<std::pair<std::vector, moderndbs::File &>, std::vector<std::pair<std::vector, moderndbs::File &>>, (lambda at


Solution

  • There's a mismatch in your question, between uint64_t and int. Assuming that this is squared away:

    You need at least C++20 in order to compile the shown code. Prior to C++20, lambdas are not default-constructible, and you attempting to default-construct your std::priority_queue.

    You need to explicitly pass the comparator to the constructor. Tested with gcc 10, with -std=c++17:

    #include <queue>
    #include <functional>
    #include <vector>
    #include <cstdint>
    
    class File{};
    
    void foo()
    {
        auto comparator = [](std::pair<std::vector<int>,
                     File &> const &a,
                     std::pair<std::vector<int>,
                     File &> const &b) {
            return a.first.front() > b.first.front();
        };
    
        std::priority_queue<std::pair<std::vector<int>,
                          File &>,
                    std::vector<std::pair<std::vector<int>,
                              File &>
                        >,
                    decltype(comparator)> pq{comparator};
    }
    

    This fails with with a default-constructor pq. gcc 10 compiles the default-constructed pq with -std=c++20.

    P.S.: consider replacing the File & with std::reference_wrapper, unless you really intend to do what the File & in std::pair will really do.