What makes you throw: it converts a pointer of type
int (*)(const void **, const void **)
type pointer
int (*)(const void *, const void *)
The latter means qsort is expected.
Such things are quite common in poor quality code. For example, when someone wants to sort an array from int s, they often write a comparison function that takes pointers to int *
int compare_ints(const int *a, const int *b) { return (*a > *b) - (*a < *b); }
and when it comes time to call qsort , they force it to the appropriate type to suppress compiler complaints.
qsort(array, n, sizeof *array, (int (*)(const void *,const void *)) compare_ints);
This is a “hack,” which leads to undefined behavior. This is obviously bad practice. What you see in your example is just a less direct version of the same “hack”.
The correct approach in such cases would be to declare the comparison function as
int compare_ints(const void *a, const void *b) { int a = *(const int *) a; int b = *(const int *) b; return (a > b) - (a < b); }
and then use it without any throws
qsort(array, n, sizeof *array, compare_ints);
In general, if you expect their comparison functions to be used as comparators in qsort (and similar functions), they should implement them with const void * parameters.