Macro-driven 条件函数的第一个参数

Macro-driven conditional first argument to a function

我有一个 API 行为如下:

#ifdef MYLIB_SINGLETON
  void* mylib_malloc(size_t size);
  void mylib_free(void* ptr);
  void mylib_log(int level, const char* msg, ...);
#else
  void* mylib_malloc(void* ctx, size_t size);
  void mylib_free(void* ctx, void* ptr);
  void mylib_log(void* ctx, int level, const char* msg, ...);
#endif

我想删除重复项。在 C++ 中,我会使用 simple-ish 模板,但这是 C header。我的选择似乎是:

就宏而言。我能做的最好的是以下内容,但我对宏还不够满意,无法相信它会尽可能干净。


#ifdef MYLIB_SINGLETON
  #define MYLIB_FUNC_ARGS(...) ##__VA_ARGS__
#else
  #define MYLIB_FUNC_ARGS(...) void* ctx, ##__VA_ARGS__
#endif

void* mylib_malloc( MYLIB_FUNC_ARGS(size_t size) );
void mylib_free( MYLIB_FUNC_ARGS(void* free) );
void mylib_log( MYLIB_FUNC_ARGS(const char* msg, ...) );

不是很糟糕,但在我看来还不够好。

编辑: 澄清一下,这不是我想出的唯一方法,只是我觉得最好的方法。特别是以下作品,但出于上述原因我不喜欢它们

// It looks like MYLIB_MAYBE_CTX alters the size parameter, instead of being a parameter in its own right.
void* mylib_malloc(MYLIB_MAYBE_CTX size_t size);

// Very confusing at a glance.
void* MYLIB_FUNC(mylib_malloc, size_t size);

我宁愿有一个对于图书馆用户来说阅读起来更直观的解决方案。沿着以下几行的东西会很好。不过据我所知,这是不可能的。

void* mylib_malloc(MYLIB_MAYBE_CTX, size_t size);
void mylib_free(MYLIB_MAYBE_CTX, void* free);
void mylib_log(MYLIB_MAYBE_CTX, const char* msg, ...);

是否有一些宏魔法可能,或者只是一些我没有看到的明显的东西,这将使我能够一次性提供这两个接口,同时仍然直观地看起来像库的 would-be 用户的函数?或者,一个权威的“不,这和你得到的一样好”的回答会让我不再担心这个。

这是一种可能的语法

#ifdef MYLIB_SINGLETON
      #define MYLIB_ARGS(...) (__VA_ARGS__)
#else
      #define MYLIB_ARGS(...) (void *ctx, ##__VA_ARGS__)
#endif

#define MYLIB_FUNC(x) x MYLIB_ARGS

void* MYLIB_FUNC(mylib_malloc)(size_t size);
void MYLIB_FUNC(mylib_free)(void* free);
void MYLIB_FUNC(mylib_log)(const char* msg, ...);