Перегрузка функции C несколькими аргументами - PullRequest
0 голосов
/ 05 июня 2018

Мне нравится voverload функции C.Я нашел следующее: Перегрузка функций в C с использованием GCC - функции с множественными аргументами .Это работает очень хорошо, но теперь я хочу выбрать функцию в зависимости от типа двух аргументов.

#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))

Но с этим кодом я получил ошибку компиляции:

ошибка: вызываемый объект не является функцией или указателем на функцию (__builtin_choose_expr (__buildin_types_compatible_p (typeof (* data), uint8_t)

Кто-нибудь является идеей, не возможно ли отправить по двум аргументам. Сама конструкция)также работает. Сбой, если я вызываю функцию с данными uint32_t и длиной uint32_t. Вызовы функций с uint8_t работают.

Спасибо за вашу помощь.

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

Возможно, это не лучшее использование перегрузки на основе типов (будь то на основе __builtin_choose_expr или стандартизированной _Generic), но вот пример, который показывает, что ваш код работает с uint32_t *data и uint32_t len.Код компилируется:

#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));
}
0 голосов
/ 05 июня 2018

Этого можно добиться с помощью C.11 _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)

Синтаксис выбора выражения с использованием __builtin_choose_expr в GCC описан в принятом ответе на вопрос, который вы цитировали в своем посте..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...