0

I like to voverload a C function. I found following: Function overloading in C using GCC - functions with mutiple arguments. This works very fine, but now i want to sellect the function based on the type of two arguments.

#define dataioWriteBin(file, data, len)                                                                                                                                                 \
    (__builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint8_t )    && __builtin_types_compatible_p(typeof(len), uint64_t ), dataioWriteBin_uint8Data_uint64Len,    \
     __builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint8_t )    && __builtin_types_compatible_p(typeof(len), uint32_t ), dataioWriteBin_uint8Data_uint32Len,    \
     __builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint32_t )   && __builtin_types_compatible_p(typeof(len), uint64_t ), dataioWriteBin_uint32Data_uint64Len,   \
     __builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint32_t )   && __builtin_types_compatible_p(typeof(len), uint32_t ), dataioWriteBin_uint32Data_uint32Len,   \
     (void)0))))(file, data, len))

But with this code i got a compile following error:

error: called object is not a function or function pointer (__builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint8_t )

Anybody a Idea, is it not possibel to dispatch on two argumnents. The construct itself does also work. It Fails wenn i call the function with uint32_t data and uint32_t length. The Function calls with uint8_t are working.

Thanks for your help.

2
  • 1
    "I like to overload a C function". Why? There might be valid cases, but you better make yours a good one before you even consider this. Commented Jun 5, 2018 at 9:10
  • There are better tools than C for this. "Birmingham screwdriver" seems apropos. Commented Jun 5, 2018 at 10:04

2 Answers 2

0

You can achieve this with C.11's _Generic:

#define uint8Data_(file, data, len)                          \
_Generic((len),                                              \
    uint64_t : dataioWriteBin_uint8Data_uint64Len,           \
    uint32_t : dataioWriteBin_uint8Data_uint32Len)

#define uint32Data_(file, data, len)                         \
_Generic((len),                                              \
    uint64_t : dataioWriteBin_uint32Data_uint64Len,          \
    uint32_t : dataioWriteBin_uint32Data_uint32Len)

#define dataioWriteBin(file, data, len)                      \
_Generic(                                                    \
    (data),                                                  \
    uint8_t * :        uint8Data_(file, data, len),          \
    const uint8_t * :  uint8Data_(file, data, len),          \
    uint32_t * :       uint32Data_(file, data, len),         \
    const uint32_t * : uint32Data_(file, data, len)          \
    )(file, data, len)

The expression selection syntax using GCC's __builtin_choose_expr is described in the accepted answer to the question you cited in your post.

Sign up to request clarification or add additional context in comments.

Comments

0

This might not be the best use of type-based overloading (whether based on __builtin_choose_expr or the standardized _Generic) but here's an example that shows that your code does work with uint32_t *data and uint32_t len. The code compiles:

#include <stdint.h>
#include <stdio.h>
//prototypes
void dataioWriteBin_uint8Data_uint64Len(FILE *f, uint8_t const *data, uint64_t len);
void dataioWriteBin_uint8Data_uint32Len(FILE *f, uint8_t const *data, uint32_t len);
void dataioWriteBin_uint32Data_uint64Len(FILE *f, uint32_t const *data, uint64_t len);
void dataioWriteBin_uint32Data_uint32Len(FILE *f, uint32_t const *data, uint32_t len);

//
#define dataioWriteBin(file, data, len)                                                                                                                                                 \
    (__builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint8_t )    && __builtin_types_compatible_p(typeof(len), uint64_t ), dataioWriteBin_uint8Data_uint64Len,    \
     __builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint8_t )    && __builtin_types_compatible_p(typeof(len), uint32_t ), dataioWriteBin_uint8Data_uint32Len,    \
     __builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint32_t )   && __builtin_types_compatible_p(typeof(len), uint64_t ), dataioWriteBin_uint32Data_uint64Len,   \
     __builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint32_t )   && __builtin_types_compatible_p(typeof(len), uint32_t ), dataioWriteBin_uint32Data_uint32Len,   \
     (void)0))))(file, data, len))

//
void use_it(void)
{
    uint32_t data[4]={};
    dataioWriteBin(stdout,data,(uint32_t)sizeof(data));
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.