5

In C++17 you can do this:

#include <iostream>
#include <algorithm>
#include <functional>

int main()
{
    double values[5] = { 1.1, 2.2, 3.3, 4.4, 5.5 };

    // Notice this:
    std::sort(values, values+5, std::greater());

    for(double v: values) std::cout << v << " ";
    std::cout << "\n";
}

You don't actually need to specify the template parameter of std::greater. It will be automatically deduced as double. That's really nice.

But wait... How?!?

There's nothing telling std::greater that the template parameter should be of type double. It's not taking any constructor parameters or anything. And the declaration of std::sort() is ostensibly like this:

template<class RandomIt, class Compare>
void sort(RandomIt first, RandomIt last, Compare comp);

so there's nothing there telling it that it should be double either.

So how?

bolov
  • 72,283
  • 15
  • 145
  • 224
Warp
  • 363
  • 2
  • 9
  • I'm on mobile, so up for grabs: it's `std::greater<>` and it has an `operator()` template instead of a fixed type. – Quentin Sep 04 '19 at 23:31
  • 2
    Possible duplicate of [What are transparent comparators?](https://stackoverflow.com/questions/20317413/what-are-transparent-comparators). tl;dr - what Quentin said. Instead of the comparator being a class template, its operator () is a template. – Fureeish Sep 04 '19 at 23:33
  • 1
    I don't agree that this is a duplicate. The linked ["duplicate"](https://stackoverflow.com/questions/20317413/what-are-transparent-comparators) has a good discussion about transparent comparators, and how they're defined - but it doesn't answer the OP's question - "how does this code work" – Marshall Clow Sep 05 '19 at 00:41
  • @MarshallClow: It works *because* the transparent comparators exist; once you know about the ``, the behavior here is obvious. Is that good enough? – Davis Herring Sep 05 '19 at 01:07
  • 1
    @DavisHerring I think there's a missing link: having a default template-argument doesn't make the template-argument-list (`<>`) omittable. It's actually the power of CTAD, which is not mentioned in the "duplicate". – cpplearner Sep 05 '19 at 02:01
  • @cpplearner: Fair enough: we could even have a deduction guide from `()` to `` if we wanted to, without allowing `<>`. (There’s no such distinction for *functions*, which probably affected my analysis.) – Davis Herring Sep 05 '19 at 04:02
  • Could someone show me how the deduction guide would be implemented to make this work? – Warp Sep 05 '19 at 19:58

1 Answers1

5

There are two different definitions for std::greater. One requires a template parameter on the type, the other does not.

You're using the second one.

This is what std::greater looks like (leaving off modifiers like constexpr and noexcept and different return types):

template <typename T = void>
struct greater
{
    bool operator () (const T& x, const T& y) { return x > y; }
};

template <>
struct greater<void>
{
    template <typename T1, typename T2>
    bool operator () (const T1& x, const T2& y) { return x > y; }
    typedef void is_transparent;
};
Marshall Clow
  • 15,972
  • 2
  • 29
  • 45
  • Yes, but _how_ does `greater()` end up at the 2nd one? – Barry Sep 05 '19 at 00:31
  • Well, it can't be the first one - because you didn't provide a template parameter; so it has to be the second one. – Marshall Clow Sep 05 '19 at 00:38
  • oops. Thanks, Davis. Fixed. – Marshall Clow Sep 05 '19 at 03:58
  • @MarshallClow: cpplearner’s point (which might also have been yours) stands: CTAD has to be mentioned here. – Davis Herring Sep 05 '19 at 04:04
  • This answer, at least all by itself, does not work. I tried it, and I'm getting the error "missing template arguments before '(' token" when trying to use it like "std::sort(values, values+5, greater());" Clearly it's expecting it to be used like "greater<>()". However, as shown in my original question, std::greater doesn't require the empty brackets. Thus my question remains unanswered. I also have to object to this being marked as a duplicate to that other post, because that other post does *not* answer the question either. – Warp Sep 05 '19 at 19:56
  • Oops. Scratch that. I was testing it with gcc 7.1, which gives erroneously an error for that code. It appears that it's not until gcc 9 that it compiles without the <> brackets. – Warp Sep 05 '19 at 20:23