1

I am using std::sort to sort an array in descending order.

#include <iostream>
#include <algorithm>
#define size 5
using namespace std;

bool descending(int x,int y){
    return x>y;
} 
int main(){
    int a[size]={5,3,7,34,2};
    sort(a,a+size,descending);
    return 0;
}

This code works. But I'm not sure why.

  1. Shouldn't descending be called with 2 arguments?
Typedragon33
  • 139
  • 7
  • 3
    `template< class RandomIt, class Compare > void sort( RandomIt first, RandomIt last, Compare comp );` expects function pointer of type `bool cmp(const Type1 &a, const Type2 &b);`. refer: [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort) – TruthSeeker Feb 16 '21 at 06:48
  • 1
    Does this answer your question? [How do function pointers in C work?](https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work) – Aykhan Hagverdili Feb 16 '21 at 07:01
  • 1
    @TruthSeeker it doesn't necessarily have to be a function pointer. Any callable object would do. – Aykhan Hagverdili Feb 16 '21 at 07:03

4 Answers4

2

Here you are not calling descending() function in your program, you are passing it to std::sort() as a function pointer which accepts a function pointer of type

bool cmp(const Type1 &a, const Type2 &b);

as its third argument.


according to cppreference , the third argument to std::sort is comp which is

comparison function object (i.e. an object that satisfies the requirements of Compare) which returns ​true if the first argument is less than (i.e. is ordered before) the second. The signature of the comparison function should be equivalent to the following:

bool cmp(const Type1 &a, const Type2 &b);

While the signature does not need to have const &, the function must not modify the objects passed to it and must be able to accept all values of type (possibly const) Type1 and Type2 regardless of value category (thus, Type1 & is not allowed, nor is Type1 unless for Type1 a move is equivalent to a copy (since C++11)).

The types Type1 and Type2 must be such that an object of type RandomIt can be dereferenced and then implicitly converted to both of them. ​

source :

std::sort

Arsenic
  • 727
  • 1
  • 8
  • 22
1

On this line sort(a,a+size,descending); the function descending is not being called at all. It is being passed to the function sort. The function sort will call descending and it will use two arguments (which it will get from the array a).

The take-away is that there are two things you can do with a function:

  • You can call it
  • a function has a value (its address), which you can pass as a parameter to another function, save in a variable, etc.

There are a few technical details here which I've skipped over. For instance, what is actually being passed in your case is a pointer to the function. But the essential idea is that functions are callable but they are also values that can be passed around just like other values.

john
  • 85,011
  • 4
  • 57
  • 81
1

Short answer:

Shouldn't descending be called with 2 arguments?

No, because you don't call it. You give it to std::sort, which will then call it, passing it elements from the array as needed.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
0

std::sort uses iterators. This means that when comparing, it dereferences the pointer to compare the actual value. This is what it looks like (when comparing, Reference: cppreference),

if(comp(*(it + n), *it)) { ... }

Once the pointer is dereferenced, in this case int pointers, it gives the int value which the iterator points to. This is why passing in bool descending(int x,int y) as the comparator method works without an issue.

D-RAJ
  • 3,263
  • 2
  • 6
  • 24