使用宏“高阶函数”生成器在C中进行函数式编程

时间:2009-05-21 17:43:07

标签: c functional-programming c-preprocessor

请注意,因为这是一个问题的地狱; - )

我想在C中使用模板函数进行泛型集合操作(​​如search,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)

3 个答案:

答案 0 :(得分:12)

如果您使用的是Linux / BSD Unix,请查看queue(3)并查看/usr/include/sys/queue.h - 之前已完成:)

答案 1 :(得分:1)

A recent question 引发了一些无耻的预处理器滥用库。

答案 2 :(得分:1)

有关信息,GCC 4.6的源代码实现了向量的类似技巧。查看其文件gcc/vec.h