Search code examples
c++builderstrcmpqsort

Getting an error on a qsort compare function


I'm using C++Builder 10.4.2 and having a problem with qsort. I rarely use qsort so I might be making a clumsy mistake. Array 'buffer' is a 2D 'char' array with more than 26,000 rows of single words.

This is the call:

qsort((void *)buffer,wordcount,sizeof(buffer[1]),sort_function);

This is the compare function:

int TForm::sort_function(const void *a, const void *b)
{
  return( strcmp((char *)a,(char *)b) );
}

This is the error message. Notice that it's complaining about sort_function for 4th argument:

search.h(46): candidate function not viable: no known conversion from 'int (__closure *)(const void *, const void *)' to 'int (*)(const void *, const void *) __attribute__((cdecl))'

What is 'int (__closure *)'? Is there a way to fix my compare function?


Solution

  • __closure is a Borland compiler extension for obtaining a pointer to a non-static class method, without regard to the type of class being used. This is most commonly used in VCL/FMX components, which allow you to assign event handlers from any class you want, which is not something that standard C++ typically allows you to do.

    qsort() expects a C-style function pointer in the 4th parameter. You can't get such a pointer to a non-static class method.

    To solve this, you need to use either:

    • a standalone function
    • a static class method
    • a non-capturing C++ lambda (C++11 or higher only)

    Since your sort_function() does not need access to your TForm object, declaring sort_function() as static would be the simplest fix:

    // .h
    
    class TForm
    {
    ...
    private:
        static int sort_function(const void *a, const void *b);
        void doSomething();
    ...
    };
    
    // .cpp
    
    int TForm::sort_function(const void *a, const void *b)
    {
        return strcmp((const char *)a, (const char *)b);
    }
    
    void TForm::doSomething()
    {
        ...
        qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
        ...
    }
    

    However, it really should be a standalone function instead since it really has no relation to your TForm class at all:

    // .cpp
    
    static int sort_function(const void *a, const void *b)
    {
        return strcmp((const char *)a, (const char *)b);
    }
    
    void TForm::doSomething()
    {
        ...
        qsort(buffer, wordcount, sizeof(buffer[1]), sort_function);
        ...
    }