1

Here is a line of code I read in a book

priority_queue<IteratorCurrentAndEnd, vector<IteratorCurrentAndEnd>, greater<>> min_heap;

where IteratorCurrentAndEnd is a class implementing a operator> method. Why can we have greater<> instead of greater<IteratorCurrentAndEnd>? I checked and read something like this,

template< class T = void >
struct greater;

But I don't really know what it means. Is it something related to the void type? What is it actually?

Thanks.

Sean
  • 2,649
  • 3
  • 21
  • 27
  • 1
    This is easy to find from cppreference: http://en.cppreference.com/w/cpp/utility/functional/greater_void . If you just google `std::greater`, cppreference's page on it comes up – Justin Jun 04 '18 at 18:51

2 Answers2

6

Until C++14, std::greater<T> was a class template based on one explicit type parameter T. It only allowed to compare two equal types. Otherwise, when comparing different types, one had to rely on conversion which can fail in the process of template argument deduction.

This has been fixed with C++14 in the sense that now there also exists a general comparison of two distinct types. Instead of using a new class template std::greater<T,U> (which possibly would not be backwards compatible and certainly also more complicate), a specialization std::greater<void> is used which did not exist before C++14. The type void is chosen for exactly this reason: as it was never used before C++14 -- comparison of voids makes no sense -- one automatically gets backwards compatibility and even avoids introducing a new class template.

As it's described in the reference, std::greater<void> now is a functor containing an operator() function template similar to

template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
{
    return std::forward<T>(lhs) > std::forward<U>(rhs);
}

This implements the general comparison between two types (and is quite the same as one would come up with nowadays).

davidhigh
  • 14,652
  • 2
  • 44
  • 75
0

Yes, it is related to the void in the snippet, but it's nothing special about void as a type itself. This syntax says that struct greater takes one template parameter (that is a type), but that it can be omitted, and in case it is omitted, void is used as that type. It's similar to default value syntax for regular functions:

void foo(int x = 7);

foo(5); // x = 5
foo(); // x = 7
Nick Mertin
  • 1,149
  • 12
  • 27