Here is a MRE
#include <string.h>
typedef char* mytype;
typedef int(*cmp)(const mytype, const mytype);
void foo(cmp f) {}
int main(void) {
foo(strcmp);
}
When I compile I get:
$ gcc mre.c -Wall -Wextra
mre.c: In function ‘foo’:
mre.c:7:14: warning: unused parameter ‘f’ [-Wunused-parameter]
7 | void foo(cmp f) {}
| ~~~~^
mre.c: In function ‘main’:
mre.c:10:9: warning: passing argument 1 of ‘foo’ from incompatible pointer type [-Wincompatible-pointer-types]
10 | foo(strcmp);
| ^~~~~~
| |
| int (*)(const char *, const char *)
mre.c:7:14: note: expected ‘cmp’ {aka ‘int (*)(char * const, char * const)’} but argument is of type ‘int (*)(const char *, const char *)’
7 | void foo(cmp f) {}
| ~~~~^
The first warning is irrelevant. But what do I do about the second? I tried changing the typedef to:
typedef int(*cmp)(mytype const,mytype const);
But that gave the exact same result. When I changed to:
typedef int(*cmp)(const char*, const char*);
it worked, but that's not preferable for obvious reasons. Another thing that worked but also is not preferable is this:
typedef const char* mytype;
typedef int(*cmp)(mytype, mytype);
So what have I missed here?
The problem I'm trying to solve is that I want to create a generic structure where the data is of type mytype
. The user of the structure is expected to implement a compare function, but I want it to work with strcmp
in case mytype
is of type char*
.
Note that mytype
not necessarily needs to be a pointer. It depends on what data type the user specifies. Also, I know that typedefing pointers is bad practice in general, but I consider this a special case because I want to typedef whatever the type is, and it may be a pointer.
The structure looks like this:
struct node {
struct node *next;
mytype data;
};
I managed to solve it with #define mytype char*
but that feels very ugly, and I would prefer if there was another way. I want it to be portable, so I don't want to use gcc extensions.