Обратите внимание, потому что это адский вопрос; -)
Я хочу использовать шаблонные функции для общих действий по сбору (таких как поиск, foreach и т. Д.) В C при сохранении статической проверки типов компилятора. Это довольно просто, когда вы используете простые обратные вызовы, как в этом примере:
#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);
но я не могу понять, как реализовать передачу параметров с препроцессором. Здесь я прошу вашей помощи, идей и предложений.
(Кстати, не говорите мне использовать функцию variadic в качестве шаблона и передавать аргумент va_list в функцию обратного вызова, потому что все это происходило из-за проверки типа :-p)