Подтвердить что ты не робот

Функциональное программирование на C с помощью генераторов с генератором "более высокого порядка"

Обратите внимание, потому что это ад, -)

Я хочу использовать функции шаблона для общих действий коллекции (например, search, 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);

но я не могу понять, как реализовать передаваемый параметр с препроцессором. Здесь я прошу вашу помощь, идеи и предложения.

(Кстати, не говорите мне использовать вариационную функцию в качестве шаблона и передавать аргумент va_list для обратного вызова, потому что все это было из-за проверки типа: -p)

4b9b3361

Ответ 1

Если вы работаете в Linux/BSD Unix, посмотрите queue (3) и зайдите в /usr/include/sys/queue.h - это было сделано до:)

Ответ 2

Недавний вопрос поднял немало бесстыдных препроцессоров, злоупотребляющих библиотеками.

Ответ 3

Для информации исходный код GCC 4.6 реализует аналогичные трюки для векторов. Посмотрите в свой файл gcc/vec.h