我正在编写一个数学库,想要进行像“add”这样的通用调用,它采用两个参数 v1 和 v2,并调用正确的函数。如果v1是vec2并且v2是vec2,那么它将调用vec2_add,如果v1是vec2并且v2是float,那么它将调用vec2_add_float。但如果 v1 是 vec3,v2 是 vec3,它将调用 vec3_add 等...底部会绘制一个小图
v1 -> vec2,v2-> vec2:调用 vec2_add v1 -> vec2, v2-> float: 调用 vec2_add_float
v1 -> vec3,v2-> vec3:调用 vec3_add v1 -> vec3,v2-> float:调用 vec3_add_float
我确实写了一个小的通用代码,如下所示:
#define add(v1, v2) _Generic((v1), \
vec2: _Generic((v2), \
vec2: vec2_add, \
float: vec2_add_float \
), \
svec3: _Generic((v2), \
vec3: vec3_add, \
float: vec3_add_float \
) \
)(v1, v2)
出于某种原因,这适用于 add_float 类型,但当我尝试将 vec2 添加到 vec2 或将 vec3 添加到 vec3 时却不起作用,给我错误消息:
‘_Generic’ selector of type ‘vec2’ is not compatible with any association
30 | vec3: _Generic((v2), \
我在这里做错了什么?
从语法上讲,
_Generic
是一个运算符,并且它的每个操作数都必须是有效的表达式,即使该操作数未被_Generic
选择。
当
v1
和 v2
都是 vec2
时,选择外部 vec2
中的 _Generic
大小写,但 vec3
大小写(我认为 svec3
是拼写错误)必须仍然有效。这种情况下的操作数是:
_Generic((v2),
vec3: vec3_add,
float: vec3_add_float
)
该
_Generic
表达式与 v2
(a vec2
)大小写不兼容,因此编译器会抱怨。
要解决这个问题,请为其指定默认情况。您可以使用带有空函数指针或错误处理函数的单独默认情况,例如:
_Generic((v2),
vec3: vec3_add,
float: vec3_add_float,
default: (void (*)(void)) 0
)
或
_Generic((v2),
vec3: vec3_add,
float: vec3_add_float,
default: ErrorHandlingFunction
)
或将其折叠到其他箱子之一中,例如:
_Generic((v2),
vec3: vec3_add,
default: vec3_add_float,
)
选择表达式必须是有效。当 v2
为
vec2
时,表达式 _Generic(v2, vec3: vec3_add, float: vec3_add_float)
无效,因为 vec3
和 float
都不与 vec2
兼容。IMO,这是通用选择的严重设计缺陷。 解决方法是使用
default
来处理常见情况,即
vec2_add
是 v1
是 vec2
,或者 vec3_add
,如果 v1
是 vec3
。#define add(v1, v2) _Generic((v1), \
vec2: _Generic((v2), \
default: vec2_add, \
float: vec2_add_float \
), \
vec3: _Generic((v2), \
default: vec3_add, \
float: vec3_add_float \
) \
)(v1, v2)