c# 向头文件添加Variadic宏(程序接口)

iyfjxgzm  于 2023-01-03  发布在  C#
关注(0)|答案(2)|浏览(181)

我在想如果我用可变参数宏来创建一个带默认参数的函数,我该如何把这个函数的原型添加到接口头文件中这样我就可以对用户隐藏基函数了.

#define Enable_Asynchronous_Clock(...) Enable_Asynchronous_Clock_Base((struct Asynch_Args){.tcnt=0,.tccr=0,.ocr=0, __VA_ARGS__})

struct Asynch_Args{ u8 tcnt;u8 tccr;u8 ocr;};
void Enable_Asynchronous_Clock_Base(struct Asynch_Args argv){
    //////
}

是否有可能为这个“Enable_Asynchronous_Clock(...)”添加一个原型。
起初,我想把它作为一个普通函数,使用if/elifs,在最后调用基函数,但我偶然发现了这个方法,并想对它进行一些实验。

dffbzjpn

dffbzjpn1#

您可以使用宏中使用的函数名称,将函数名称括在圆括号中:

/* impl.h */
#define Enable_Asynchronous_Clock(...) Enable_Asynchronous_Clock((struct Asynch_Args){.tcnt=0,.tccr=0,.ocr=0, __VA_ARGS__})

struct Asynch_Args{ u8 tcnt;u8 tccr;u8 ocr;};
void (Enable_Asynchronous_Clock)(struct Asynch_Args);
/* impl.c */
#include "impl.h"

void (Enable_Asynchronous_Clock)(struct Asynch_Args argv){
    //////
}
ruarlubt

ruarlubt2#

您可能不希望允许向函数传递任意参数,因此可以根据传递到的参数数量选择默认参数,如下所示:

#define foo(...) CONCAT(foo_, ARG5(__VA_ARGS__, 5, 4, 3, 2, 1, 0))(__VA_ARGS__)

#define CONCAT(X, Y) CONCAT_(X, Y)
#define CONCAT_(X, Y) X ## Y

#define ARG5(_0, _1, _2, _3, _4, _5, ...) _5

void foo_5(int mandatory1, int mandatory2, int optional1, int optional2, int optional3)
{
}

#define foo_4(M1, M2, O1, O2) foo_5(M1, M2, O1, O2, 7)
#define foo_3(M1, M2, O1) foo_5(M1, M2, O1, 7, 7)
#define foo_2(M1, M2) foo_5(M1, M2, 7, 7, 7)

演示请参见godbolt
您可能会为这些foo_N函数/宏中的一些添加overloaded变体-尽管我不建议为类型隐式地从一个转换为另一个(如intdouble),因为这可能太容易出错(如使用foo(7, 7, 7),而使用foo(7, 7, 7.0))。
诚然,基本函数/宏对用户仍然可见,但我并不认为这是一个大问题。

相关问题