Why do I need pass a comparator to construct a priority_queue when it is a lambda, but not when it is std::greater?

  • A+

I am reading a code sample from cppreference:

#include <functional> #include <queue> #include <vector> #include <iostream>  template<typename T> void print_queue(T& q) {     while(!q.empty()) {         std::cout << q.top() << " ";         q.pop();     }     std::cout << '/n'; }  int main() {     std::priority_queue<int> q;      for(int n : {1,8,5,6,3,4,0,9,7,2})         q.push(n);      print_queue(q);      std::priority_queue<int, std::vector<int>, std::greater<int> > q2;      for(int n : {1,8,5,6,3,4,0,9,7,2})         q2.push(n);      print_queue(q2);      // Using lambda to compare elements.     auto cmp = [](int left, int right) { return (left ^ 1) < (right ^ 1);};     std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);      for(int n : {1,8,5,6,3,4,0,9,7,2})         q3.push(n);      print_queue(q3);  } 

I am not sure why q2 does not need to be initialized? I.e. Instead of having

std::priority_queue<int, std::vector<int>, std::greater<int> > q2;

in the original code, I guess we should have something like

std::priority_queue<int, std::vector<int>, std::greater<int> > q2(std::greater<int>());

So why when we have an customized compare function, we can omit the initializer for q2 but not for q3 in the code sample?


The key difference is that std::greater is default constructible, but closure types (lambdas) are not.

Thus, the queue needs to be given a lambda object to copy construct its comparator from as a constructor argument.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: