Язык Си является языком статической типизации.Он не обладает способностями отражения во время выполнения, как это делают другие языки.Он также не предоставляет способов для создания произвольных вызовов функций из типов, предоставляемых во время выполнения.У вас должен быть какой-то способ узнать, что такое сигнатура функции is_odd
и сколько параметров она принимает и каковы типы этих параметров.Он даже не знает, когда он достиг конца списка ... аргументов;вам нужен явный терминатор.
enum function_signature {
returns_bool_accepts_int,
returns_bool_accepts_float,
returns_bool_accepts_int_int,
};
typedef bool (*function_returning_bool_accepting_int)(int);
typedef int (*function_generates_int)();
void for_all(function_signature signature, ...)
{
va_list ap;
va_start(ap, signature);
switch (function_signature)
{
case returns_bool_accepts_int:
{
function_returning_bool_accepting_int fn = va_arg(ap, function_returning_bool_accepting_int);
function_generates_int generator;
do {
generator = va_arg(ap, function_generates_int);
if (generator) fn(generator());
} while (generator);
}
break;
... etc ...
}
}
Ваша проблема в том, что QuickCheck был разработан для использования преимуществ высокой динамической программируемости JavaScripts, чего-то не хватает в C.
Обновление Есливы разрешаете произвольные сигнатуры функций, а затем вам нужен способ снова сделать его статичным, скажем, путем предоставления вызывающей стороне соответствующих адаптеров.
typedef void (*function_pointer)();
typedef bool (*function_applicator)(function_pointer, function_pointer);
void for_all(function_applicator apply, ...)
{
va_list ap;
va_start(ap, apply);
function_pointer target = va_arg(ap, function_pointer);
function_pointer generator;
do {
generator = va_arg(ap, function_pointer);
if (generator) apply(target, generator);
} while (generator);
}
// sample caller
typedef bool (*function_returning_bool_accepting_int)(int);
typedef int (*function_returning_int)();
bool apply_one_int(function_pointer target_, function_pointer generator_)
{
function_returning_bool_accepting_int target = (function_returning_bool_accepting_int)target_;
function_returning_int generator = (function_returning_int)generator_;
return target(generator());
}
for_all(apply_one_int, is_odd, generated_values1, generated_values2, (function_pointer)0);
}