我正在尝试使用宏在C中编写一些可重用的通用类型安全代码,类似于klib的工作方式:

#define Fifo_define(TYPE) \
   \
   typedef struct { \
       TYPE *head; \
       TYPE *tail; \
       size_t capacity; \
   } Fifo_##TYPE, *pFifo_##TYPE; \
   \
   inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) { \
       Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE)); \
       TYPE * data = calloc(capacity, sizeof(TYPE)); \
       fifo->head = data; \
       fifo->tail = data; \
       fifo->capacity = capacity; \
   }

// define macros

#define Fifo(TYPE) Fifo_##TYPE
#define Fifo_init(TYPE, capacity) Fifo_##TYPE_init(capacity)


然后,我将其与任何类型参数一起使用:

Fifo_define(int32_t);
...
Fifo(int32_t) *myFifo = Fifo_init(int32_t, 100);


但是,编写此文件非常费事且容易出错,没有IDE编辑器支持(IntelliSense),因此我想知道是否有任何技巧可以使我(也许)添加一些定义,然后包括文件,而不必结束每行与\

就像是:

// no idea how to do this, just checking if similar concept is possible

#define FIFO_TYPE int
#define FIFO_NAME Fifo_int

#include <generic-fifo.h>

#undef FIFO_NAME
#undef FIFO_TYPE


我会以某种方式获得所有正确的struct和功能。问题是这些宏中有很多参数串联,因此我不确定是否可以用比第一个片段更简单的方式来完成?

最佳答案

在这种情况下,不建议这样做,但是您可以执行类似X-macros的操作:

#define SUPPORTED_TYPES \
  X(int)                \
  X(double)             \
  X(char)

#define X(TYPE)         \
   typedef struct {     \
       TYPE *head;      \
       TYPE *tail;      \
       size_t capacity; \
   } Fifo_##TYPE, *pFifo_##TYPE;
SUPPORTED_TYPES
#undef X

#define X(TYPE)                                          \
inline Fifo_##TYPE * Fifo_##TYPE##_init(size_t capacity) \
{                                                        \
  Fifo_##TYPE * fifo = calloc(1, sizeof(Fifo_##TYPE));   \
  TYPE * data = calloc(capacity, sizeof(TYPE));          \
  fifo->head = data;                                     \
  fifo->tail = data;                                     \
  fifo->capacity = capacity;                             \
}
SUPPORTED_TYPES
#undef X


但这并不能真正改善情况。它摆脱了单个丑陋的Fifo_define宏的需要,因此您可以将代码分成几个部分。但是宏观混乱仍然存在。



我会建议一些完全不同的方法。两个建议:


在运行时以经典的C方式处理类型通用的东西。使用回调。如有需要,请使用枚举跟踪使用的类型。
C11 _Generic允许使用各种类型的安全技巧,并可用于逐步淘汰此类混乱的宏。 Example that implements "functors"。宏本身保持最小,并键入了各种类型的不同实现。 (通常,当您进行类型通用编程时,通常这就是您要做的。)

10-08 15:10