Difference between std::greater<int>() and std::greater<int>?

Manohar picture Manohar · May 29, 2017 · Viewed 10.6k times · Source

This code works:

#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
int main(){
    priority_queue<int,vector<int>,greater<int> > pq;
    pq.push(1);
    cout<<pq.top()<<endl;
}

But,this code does not compile:

#include <iostream>
#include <queue>
#include <vector>
#include <functional>
using namespace std;
int main(){
    priority_queue<int,vector<int>,greater<int>() > pq;
    pq.push(1);
    cout<<pq.top()<<endl;
}

Why?
All I understand is that greater<int>() is a function object and priority_queue accepts a binary predicate as third argument and that predicates are a special type of functors. But how does the pair of braces make that difference.

Answer

Vlad from Moscow picture Vlad from Moscow · May 29, 2017

In this declaration

priority_queue<int,vector<int>,greater<int> > pq;

the type template argument greater<int> corresponds to the type of a structure.

In this declaration

priority_queue<int,vector<int>,greater<int>() > pq;

the type template argument greater<int>() corresponds to the type of a function that has no parameters and has the return type greater<int>

The class template std::priority_queue expects that the argument will be of a function object type that is a pointer to function or a class type that has a function operator.

To make it more clear compare for example these declarations

std::vector<int()> v1;

and

std::vector<int (*)()> v2;

For the first declaration the compiler will issue an error because the operator sizeof may not be applied to a function type int() and the vector will be unable to allocate memory for its elements. Here int() used as a type template argument is not an expression. It is a type-id.

In the second declaration the vector deal with pointers to function and it can allocate memory for its elements that are pointers.