I'm trying to understand the difference in the following two cases. In both, I introduce a comparator as a lambda function:
auto comp = [](int x, int y) { return x%2 < y%2; };
But then, if I want to use it with a sort, I can simply write
sort(vec.begin(), vec.end(), comp);
while for a class templated on a comparator, e.g. a priority_queue I need a wrapper:
priority_queue<int, decltype(comp)> my_queue;
to pass it as a template parameter.
The sort function itself is templated on a comparator class, yet it's somehow works without a decltype. Is there an implicit conversion that works for a sort
, but doesn't work in the second case?
CodePudding user response:
This is all about template argument deduction. The overload of std::sort
that you are calling is declared as
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );
and when you call it like
sort(vec.begin(), vec.end(), comp);
The compiler goes through the template argument deduction steps to determine what RandomIt
and Compare
are based of the types of the variables passed to the function.
In the case of your priority_queue
you don't get this because there are no variables to deduce types from. Because of that you have to specify the template arguments yourself.
That said, starting in C 17 we now have class template argument deduction (CTAD) and we can use the argument supplied to the constructor to deduce the template parameters of the class. For instance if you want your priority_queue
to use a std::vector<int>
as the underlying container and keep the order using comp
then you can do that with
priority_queue my_queue(comp, std:vector<int>{});