尝试使用_Generic
重载C编程语言中的函数。找到了例子:
这个例子:
#include <stdio.h>
#include <math.h>
void display_float(float dispid) ;
void display_int(int dispid) ;
void display_void(void) ;
#define display(x) _Generic((x), \
float: display_float, \
int: display_int, \
default: display_float \
)(x)
void display_void(void){
printf("display id: 0\n") ;
}
void display_float(float dispid){
printf("display id: %f\n", dispid) ;
}
void display_int(int dispid){
printf("display id: %d\n", dispid) ;
}
void main(void){
display(5) ;
display(6.5) ;
}
现在我也想用display()
重载该函数。意味着该函数将接收void
,调用函数display_void()
,并显示0。似乎无法做到这一点。任何帮助将不胜感激。
编辑1:
另外,请参见示例here。我认为,其中一个示例是传递指向void的指针。可以实现吗?
答案 0 :(得分:4)
好的。 Overload Macro on Number of Arguments。
void display_float(float dispid) ;
void display_int(int dispid) ;
void display_void(void) ;
#define _display_1(x) _Generic((x), \
float: display_float, \
int: display_int, \
default: display_float \
)(x)
#define _display_0() display_void()
#define _display_N(_0,_1,N,...) _display_ ## N
#define display(...) _display_N(_0,##__VA_ARGS__,1,0)(__VA_ARGS__)
int main() {
display();
display(1);
display(1.1);
}
在godbolt上进行了测试。
请注意,, ##__VA_ARGS__
是C标准中未描述的gcc extension。
答案 1 :(得分:1)
尝试重载C编程语言中的函数
C11没有任何function overloading ,而 _Generic
是genericity 的代表,没有< / em>是否超载,请通过阅读n1570进行检查。考虑切换到提供函数重载的C ++(或什至更好的Rust)。请注意,对C函数使用void
(不是void*
,而只是void
)参数是非法的,因此C中没有任何"top"超类型,这将是其他类型的超类型(并且由于calling conventions和ABI的考虑,使得C成为低级编程语言,有时甚至称为“ {{3 }}汇编程序”)。请阅读有关portable和abstract interpretation的更多信息。
如果_Generic
是用于重载,则C11标准委员会的成员-所有编程语言专家和足够好的英语作者-都应将其命名为_Overload
,但他们明智地没有这么做。
深思熟虑(假设stderr
和stdin
都像您希望它们正常工作一样):
假设的display(stderr)
或display(*stdin)
或display("abc")
呢?
(以下错误建议,后面有更好的建议)
(这不起作用!)
您的display_void
应该接受一些争论,例如
void display_void(void*p) { printf("p@%p\n", p);
那么您可能会有:
#define display_anything(P) display_void((void*)(&(P)))
使用
#define display(x) _Generic((x), \
float: display_float, \
int: display_int, \
default: display_anything \
)(x)
由于这行不通(而且行不通),因此以其他方式设计代码。例如,考虑使用一些type systems,例如tagged union。从Glib的here实现中获取灵感。