我有一个这样的宏:
#define ptapply(pt, ret_type, identifier, ...) ((ret_type (*)()) pget(pt, identifier))(pt __VA_OPT__(,) __VA_ARGS__)
pget
返回一个 void *
,我将其转换为函数指针并调用。因为我不知道参数的数量及其类型,所以我必须使用 ret_type (*)()
,这在大多数情况下都很好,但如果其中一个参数具有 float
、char
、short
等类型或其他事情会变得混乱,因为 C 的默认升级规则将这些类型转换为 double
并且int
。如果我能以某种方式在 typeof
中的每个参数上使用 __VA_ARGS__
,我可以将 void *
指针转换为确切的函数指针类型,但我不知道如何。有办法吗?
很简单 - 在参数数量上重载宏并在每个宏元素上应用
__typeof__
。我喜欢以下超载风格:
#include <stdio.h>
void *pget(int, int) {
return dprintf;
}
#define TYPES_1(a) __typeof__(a)
#define TYPES_2(a, ...) __typeof__(a), TYPES_1(__VA_ARGS__)
#define TYPES_3(a, ...) __typeof__(a), TYPES_2(__VA_ARGS__)
#define TYPES_4(a, ...) __typeof__(a), TYPES_3(__VA_ARGS__)
#define TYPES_N(_4,_3,_2,_1,_0,N,...) TYPES_##N
#define TYPES(...) \
TYPES_N(0 __VA_OPT__(,) __VA_ARGS__,4,3,2,1)(__VA_ARGS__)
#define ptapply(pt, ret_type, identifier, ...) \
((ret_type (*)(__typeof__(pt), TYPES(__VA_ARGS__))) pget(pt, identifier))\
(pt __VA_OPT__(,) __VA_ARGS__)
int main() {
ptapply(1, int, 0, "%s %d\n", "Hello", 5);
}