Passing Function Pointers

I need to use the std::qsort() function to sort variables in a vector of a data member of a class. So this is supposed to exercise the use of extern "C" to pass the function pointer into std::qsort().

Honestly, I'm at a complete loss, sltsort() works fine, but I'm not sure what to do to get sqsort() to work. Here is what I have:

HEADER
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef SORTABLEBASE_H
#define SORTABLEBASE_H

#include <vector>
#include <cstdlib>
#include <algorithm>

class SortableBase {
public:
  void printFirst(const unsigned long& number) const;
  void printLast(const unsigned long& number) const;
protected:
  SortableBase(const std::vector<int>& data);
  std::vector<int> m_data;
};


//Practicum 4
extern "C"
int compareDescending(const void* x, const void* y);

class Sortable : public SortableBase {
    
public:
    
    class DescendingComparer {
    public:
        bool operator()(const int& x, const int& y) const;
    };
    
    Sortable(const std::vector<int>& data);
//    extern "C"
    
    void stlsort ();
    void sqsort ();
    
};


#endif



.CPP FILE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "sortablebase.h"

#include <cassert>
#include <iostream>

SortableBase::SortableBase(const std::vector<int>& data) :
m_data(data) {assert(!data.empty());}

void SortableBase::printFirst(const unsigned long& number) const{
  assert(number<=m_data.size());
  for(size_t i=0; i<number; ++i)
    std::cout << m_data[i] << ' ';
  std::cout << std::endl;
}

void SortableBase::printLast(const unsigned long& number) const {
  assert(number<=m_data.size());
  for(size_t i=m_data.size()-1; i>=m_data.size()-number; --i)
    std::cout << m_data[i] << ' ';
  std::cout << std::endl;
}


//Practicum 4
Sortable::Sortable(const std::vector<int>& data) : SortableBase(data)
{
    
}

bool Sortable::DescendingComparer::operator()(const int& x, const int& y) const {
    
    if(x >= y) return 1;
    else return 0;
}

void Sortable::stlsort () {
    
    DescendingComparer compare;
    std::sort(m_data.begin(), m_data.end(), compare);
    
}

//extern "C"
int compareDescending(const void* x, const void* y) {
    
    if(x > y) return -1;
    //if(x == y) return 0;
    if(x < y) return 1;
    
}

void Sortable::sqsort() {
    
   std::qsort(&m_data[0], m_data.size(), sizeof(int), compareDescending);
}


Any input to help me spot the problem would be greatly appreciated. It's 2:48am, and I'm phasing out, so it's most likely a dumb mistake.

Thanks!
Why is this an execise of the use of extern "C"?
I don't have time to properly review your code, but the compareDescending() function takes void pointers, but the thing you are sorting is not supposed to be addresses but ints.

1
2
3
4
5
6
7
int compareDescending(const void* x, const void* y) {
    
    if(*(const int*)x > *(const int*)y) return -1;
    //if(x == y) return 0;
    if(*(const int*)x < *(const int*)y) return 1;
    
}

Hope this helps.
@chenqi07 - I wont pretend to know enough about coding to give a good explanation. But I think it's because std::qsort() is a C function and it needs the function it points to to be external?

@Duoas - Thanks! This might just do the trick, I was hitting that wall of exhaustion. I'll give it a shot and let you all know what happens.
The extern "C" is always necessary if you want to call a C function from C++.
@hanst99 - Thanks!

@Duoas - I'm in your debt, this worked beautifully. However, if you have a moment, could you give a brief explanation as to what is going on here? I'm assuming you are doing some sort of dereferencing? I want to make sure I understand in case I have to use something like this again.

Thanks!
closed account (zwA4jE8b)
What is happening is casting the 'void pointer' to a 'const int pointer' and then dereferencing it.
Void pointer can point to anything. So your parameter can be any type of pointer. However in your case since you are explicitly casting it to an int* you need to make sure you pass it a valid datatype.
Last edited on
The qsort() function(s) don't care what your data type is. But your comparison functions do... however, C has no generics outside of requiring your comparision function to take void pointers as arguments. But your comparison function is specific to type anyway, so inside the function you can just cast the arguments to the correct type.
@ CreativeMFS and Duoas:

Thank you, that makes perfect sense. Very useful knowledge for the future!
Topic archived. No new replies allowed.