0

I have looked at the following threads, but they do not seem to help resolve the issue:

Function pointer to member function - this thread does not help because the access is made within main and not another class

one class should invoke method of another class using a function pointer - I could not follow the accepted answer as it is not clear to me how to use <functional> header.

I have a Useful Function class, UF, in which I declare and define all common utility functions for my program. One of these functions is

int UF::compar_dbl_asc(const void *a, const void *b)//comparator for sorting 
{                                                   //array of double in ascending order
    int aa = *((int *)a), bb = *((int *)b);
    if (base_arr_dbl[aa] < base_arr_dbl[bb])
        return -1;
    if (base_arr_dbl[aa] == base_arr_dbl[bb])
        return 0;
    if (base_arr_dbl[aa] > base_arr_dbl[bb])
        return 1;
}

This is a comparator function that I intend to use within qsort() for sorting doubles in ascending order.

Within UF class definition, I also have double* base_arr_dbl; as a declaration. This is the array of values (doubles) that qsort will use.

Now, in a different class of mine named SEP, I have a function, fn1 wherein I would like to have base_arr_dbl point to a local (to fn1) double array and I would like to invoke qsort using the comparator function in UF. To be very specific although this is possibly not needed, I do not sort the actual values' array, but will sort an array of indices sortedindices[], such that sortedindices[0] will hold the index of the smallest entry in base_arr_dbl[] array. That is, the sorted order is base_arr_dbl[sortedindices[0]], base_arr_dbl[sortedindices[1]], etc.

So, I do this:

void SEP::fn1(UF *uf) {

    double ratio[100];
    //populate ratio's entries
    //Now, sort ratio's entries.
    uf->set_base_arr_dbl(ratio); //This function is defined as
   //void UF::set_base_arr_dbl(double *ptr) { base_arr_dbl = ptr; }
    qsort(sortedindices, 100, sizeof(double), uf->compar_dbl_asc);

}

However, the line qsort(sortedindices, 100, sizeof(double), uf->compar_dbl_asc); throws the following compile time error:

error C3867: 'USEFUL_FUNCTIONS::compar_dbl_asc': non-standard syntax; use '&' to create a pointer to member

I tried having &uf->compar_dbl_asc but that gives the error:

error C2276: '&': illegal operation on bound member function expression

Any way to help resolve this is appreciated.

Tryer
  • 3,580
  • 1
  • 26
  • 49
  • 3
    *"I have a Useful Function class, UF, in which I declare and define all common utility functions for my program"* That sounds like such a horrible design – Cory Kramer Sep 25 '17 at 19:16
  • 3
    Why not have a namespace instead? Do your utility functions require state? – AndyG Sep 25 '17 at 19:17
  • 2
    And otherwise, can't these utility functions be `static` within the class so that you wouldn't require an instance? – AndyG Sep 25 '17 at 19:18
  • @AndyG I am not knowledgeable about what it means for functions to require states. Could you elaborate? Also, would that help resolve this function pointer issue? – Tryer Sep 25 '17 at 19:19
  • 2
    @Tryer: I mean member variables. Does `UF` have member variables, and if so, why? It seems like you have a design problem that you should solve first. We could help you write code that would theoretically work in this design, but it would encourage bad design principles. – AndyG Sep 25 '17 at 19:20
  • @CoryKramer could you indicate whether that would lead to performance related issues? Also, what are good ways to have commonly used utility functions defined and declared? – Tryer Sep 25 '17 at 19:20
  • The syntax for pointer to member function is not `&uf->compar_dbl_asc` but `&class_name::compar_dbl_asc`. However, that will never work for the C function `qsort` which knows absolutely nothing about member functions. – Bo Persson Sep 25 '17 at 19:21
  • @Tryer: The most common way is to write a namespace with the functions. You could name it `utility`. `&utility::compar_dbl_asc` would look better than what you have – AndyG Sep 25 '17 at 19:21
  • @AndyG interestingly, it was to have this `qsort` work that I had to introduce my very first variable, `double* base_arr_dbl;` within UF class. Otherwise, there are no variables, only public member functions. Let me look into namespaces and see if that would help resolve the issue. – Tryer Sep 25 '17 at 19:24
  • @BoPersson so what you are saying is that with this current design, there is no way to get this done. Namespace is the only way? – Tryer Sep 25 '17 at 19:28
  • You can never get a C function to directly call a C++ member function. Indirection through a non-member helper function might work though. – Bo Persson Sep 25 '17 at 19:36

1 Answers1

2

As the compiler clearly tells in the error messages, neither uf->compar_dbl_asc nor &(uf->compar_dbl_asc) is appropriate for use as an argument to qsort.

You can use compar_dbl_asc as an argument to qsort using one of the following approaches.

  1. Make compar_dbl_asc a static member function of the class.
  2. Better yet, create a namespace for your app and define compar_dbl_asc in the namespace. UF could be that namespace unless it must be a class for some other reasons.

Another choice would be forego use of qsort in favor of std::sort. The latter gives you more options. You can use a functor or a lambda function when you use std::sort, which will allow you to use UF::compar_dbl_asc.

std::sort(sortedindices, sortedindices+100,
          [=uf](int a, int b) { return uf->compar_dbl_asc(a, b); });

One thing to note is that if you choose the last approach, the signature of UF::compar_dbl_asc can be changed to a more user friendly variation.

bool UF::compar_dbl_asc(int a, int b)
   return (base_arr_dbl[a] < base_arr_dbl[b]);
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thanks. Let me look into namespaces. I am guessing, like classes, namespaces would also be declared in the main header file? – Tryer Sep 25 '17 at 19:26
  • @R Sahu I think I will choose option 2, of namespace. Could you indicate what the syntax of `qsort(sortedindices, 100, sizeof(double), uf->compar_dbl_asc);` would have to be changed to? I will declare `UF` as the name of the namespace. I don't need to have it as a class. – Tryer Sep 25 '17 at 19:33
  • @Tryer, use `UF::compar_dbl_asc`. – R Sahu Sep 25 '17 at 19:34