It is a C++14 standard library feature called transparent comparators.
The below declarations can both be compiled
std::set<int, std::greater<int>> s1;
std::set<int, std::greater<>> s2;
The second variant allows for a heterogeneous comparison. Not a big deal in the case of int
but consider the example from N3657:
std::set<std::string> s = /* ... */;
s.find("key");
In old C++11 this will construct a string
temporary in order to
invoke less(string, string)
.
With a transparent comparator in C++14, less::operator() (const string&, const char*)
1 will be generated automatically which will invoke bool operator< (const string&, const char*)
, thus avoiding the temporary.
The way it's implemented is:
template< class T = void >
struct greater;
template <> struct greater<void> {
template <class T, class U> auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) > std::forward<U>(u));
};
That is, when no T
is specified, it defaults to void
, which in C++14 has a specialization that accepts heterogeneous parameters. The assumption here is that no-one would use std::greater<void>
in older code, so the risk of existing code breaking is small.
For more details see the proposals N3421, which introduces the "diamond operators", and N3657, which introduces std::is_transparent
.
1 Disclaimer: the exact deduced types may be different, this is just to illustrate the core concept without getting into too much detail.