【问题标题】:Function Overload C multiple arguments函数重载 C 多个参数
【发布时间】:2018-06-05 07:01:41
【问题描述】:

我喜欢重载一个 C 函数。我发现以下内容:Function overloading in C using GCC - functions with mutiple 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))

但是使用这段代码我得到了一个编译错误:

错误:被调用的对象不是函数或函数指针 (__builtin_choose_expr(__builtin_types_compatible_p(typeof(*data), uint8_t)

任何人都有一个想法,难道不可能同时发送两个论据吗?构造本身也可以工作。它失败了,我用 uint32_t 数据和 uint32_t 长度调用函数。使用 uint8_t 的函数调用正在运行。

感谢您的帮助。

【问题讨论】:

  • “我喜欢重载一个 C 函数”。为什么?可能有有效的案例,但您最好在考虑这一点之前先做好自己的案例。
  • 在这方面有比 C 更好的工具。 "Birmingham screwdriver" 似乎很合适。

标签: c gcc


【解决方案1】:

您可以通过 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)

accepted answer to the question you cited in your post 中描述了使用 GCC 的 __builtin_choose_expr 的表达式选择语法。

【讨论】:

    【解决方案2】:

    这可能不是基于类型重载的最佳用途(无论是基于 __builtin_choose_expr 还是标准化的 _Generic),但这里有一个示例表明您的代码确实适用于 uint32_t *datauint32_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));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 2012-01-31
      • 1970-01-01
      相关资源
      最近更新 更多