【发布时间】:2010-10-28 00:11:00
【问题描述】:
请注意,因为这是一个地狱般的问题;-)
我想在 C 中为通用集合操作(如搜索、foreach 等)使用模板函数,同时保持编译器静态类型检查。当您使用本例中的简单回调时,这相当简单:
#define MAKE_FOREACH(TYPE)\
void foreach_##TYPE (TYPE[n] array, int n, void(*f)(TYPE)) {\
for(int i = 0; i < n; i++) {\
f(array[i]);\
}\
}
因此您可以执行以下操作:
MAKE_FOREACH(int)
MAKE_FOREACH(float)
void intcallback(int x){
printf("got %d\n", x);
}
void floatcallback(float x){
printf("got %f\n", x);
}
int main(){
int[5] iarray = {1,2,3,4,5};
float[5] farray = {1.0,2.0,3.0,4.0,5.0};
foreach_int(iarray, 5, intcallback);
foreach_float(farray, 5, floatcallback);
}
如果我想用返回类型实现回调,例如创建一个“map”函数,我可以这样做:
#define MAKE_MAP(TYPE, RTYPE)\
RTYPE* map_##TYPE (TYPE[n] array, int n, RTYPE(*f)(TYPE)) {\
RTYPE* result = (RTYPE*)malloc(sizeof(RTYPE)*n);\
for(int i = 0; i < n; i++) {\
result[i]=f(array[i]);\
}\
}
到目前为止,一切都很好。现在问题来了,当我希望我的回调函数接受任意数量的类型化参数时。
这个想法是这样的:
#define MAKE_MAP(TYPE, RTYPE, ...)\
RTYPE* map_##TYPE (TYPE[n] array, int n, RTYPE(*f)(TYPE, __VA_ARGS__), __VA_ARGS__)
/*this would work for the declaration (because just the types would be enough)
but the parameter names are missing :-s*/ \
{\
RTYPE* result = (RTYPE*)malloc(sizeof(RTYPE)*n);\
for(int i = 0; i < n; i++) {\
result[i]=f(array[i], /*here the names of the parameters, in order*/);\
}\
}
所以,如您所见,我可以将地图函数声明为:
MAKE_MAP(int, float, char)
给予:
float* map_int(int[n] array, int n, float(*f)(int, char), char);
但我不知道如何实现通过预处理器传递的参数。我在这里寻求您的帮助、想法和建议。
(顺便说一句,不要告诉我使用可变参数函数作为模板并将 va_list 参数传递给回调,因为所有这些都是因为类型检查:-p)
【问题讨论】:
-
如果我稍微用力一点,这个方形钉子就可以装进我的圆孔了!!!!
-
感谢标记此“预处理器滥用”。我现在正在考虑如何编写 MAKE_PROGRAM() 宏。
-
这肯定是预处理器滥用,但是哦,如此时尚的模板元编程真的只是C++模板系统滥用吗?有时,唯一明智的答案是将工具推到其可用性的边缘。
-
+1 表示有趣的预处理器滥用。
标签: c functional-programming c-preprocessor