Peter Varo
Peter Varo

Reputation: 12160

Is function pointer type in _Generic assoc-list not working as expected?

I was experimenting with "hacking" the type-system, by not restricting the function pointer argument to accept a function with a specific type of arguments. However, I still wanted to make it type-safe, so I thought I will combine this "hack" with the possibilities of the _Generic keyword.

I have the following four functions:

#include <stdio.h>   /* printf() */
#include <stdlib.h>  /* EXIT_SUCCESS */

static void
function_i(int *i)
{
    printf("%d\n", *i);
}


static void
function_f(float *f)
{
    printf("%.2ff\n", *f);
}


static void
caller(void(*func)(),
       void *arg)
{
    func(arg);
}


static void
except(void(*func)(),
       void *arg)
{
    printf("unsupported type\n");
}

The first and second will be passed to the third, and I want to make sure, if the type of the function and the argument passed to the third is not right, then the fourth function will be called. Therefore I created the following _Generic selector:

#define handler(func, arg) _Generic((func), \
    void(*)(int*): _Generic((arg),          \
        int*    : caller,                   \
        default : except),                  \
    void(*)(float*): _Generic((arg),        \
        float*  : caller,                   \
        default : except),                  \
    default: except)(func, arg)

And then I called them:

int main(void)
{
    int   i = 12;
    float f = 3.14f;

    void(*func_ptr_i)(int*)   = function_i;
    void(*func_ptr_f)(float*) = function_f;

    handler(function_i, &i);
    handler(function_f, &f);

    handler(func_ptr_i, &i);
    handler(func_ptr_f, &f);

    return EXIT_SUCCESS;
}

The output is very interesting:

unsupported type
unsupported type
12
3.14f

I expected this to work for the first two cases as well, without the need to create a specific function pointer variable for the passed functions. The question is: is this an implementation error in clang's _Generic, or this is the expected behavior? Is so, I'm very curious about why exactly? And how to make it work without creating extra function pointers?

Thanks in advance!


SYS-INFO:

compiler: Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
flags:    cc -std=c11 -Wall -v -g

Upvotes: 3

Views: 448

Answers (1)

Jens Gustedt
Jens Gustedt

Reputation: 78923

The problem that you are facing is that the choice expression of _Generic is not evaluated. If it would be, your function names would decay to function pointers and everything would work.

Adding a & to your choice expression should fix that.

Upvotes: 3

Related Questions