我们如何申请过的va_list非可变参数的功能? [英] How can we apply a non-vararg function over a va_list?

查看:164
本文介绍了我们如何申请过的va_list非可变参数的功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我移植的快速检查的单元测试框架为C(见工作$在 GitHub的 C $ C)。语法是:

I'm porting the QuickCheck unit test framework to C (see the working code at GitHub). The syntax will be:

for_all(property, gen1, gen2, gen3 ...);

其中,属性是要测试的功能,例如布尔is_odd(INT)第一代的第二代等,都是产生输入值属性。一些产生整数,一些生成字符,一些生成字符串,等

Where property is a function to test, for example bool is_odd(int). gen1, gen2, etc. are functions that generate input values for property. Some generate integers, some generate chars, some generate strings, and so on.

for_all 将接受任意输入的功能(任意数量的参数,任何类型的参数)。 for_all 将运行发电机组,创建测试值传递给物业功能。例如,属性 is_odd 是类型的函数布尔F(INT) for_all 将使用生成创建100测试用例。如果属性返回其中任何虚假, for_all 将打印违规的测试用例值。否则, for_all 将打印SUCCESS

for_all will accept a function with arbitrary inputs (any number of arguments, any types of arguments). for_all will run the generators, creating test values to pass to the property function. For example, the property is_odd is a function with type bool f(int). for_all will use the generates to create 100 test cases. If the property returns false for any of them, for_all will print the offending test case values. Otherwise, for_all will print "SUCCESS".

因此​​, for_all 应使用的va_list 进入发电机。一旦我们调用发电机的功能,我们如何将它们传递到属性函数?

Thus for_all should use a va_list to access the generators. Once we call the generator functions, how do we pass them to the property function?

如果 is_odd 的类型为布尔F(INT),怎么会,我们实现一个函数适用()有语法如下:

If is_odd has the type bool f(int), how would we implement a function apply() that has this syntax:

apply(is_odd, generated_values);

次生问题

请参阅 SO

我们如何聪明地打印失败的测试案例的任意值?测试例可以是一个单一的整数,或两个字符,或者是字符串,或上述的一些组合?我们不会预先知道是否使用:

How can we intelligently print the arbitrary values of a failing test case? A test case may be a single integer, or two characters, or a string, or some combination of the above? We won't know ahead of time whether to use:


  • 的printf(%d个%D \\ n,some_int,some_int,some_int);

  • 的printf(%C \\ Na_character);

  • 的printf(%s%S \\ n,通过对a_string,a_struct_requiring_its_own_printf_function);

  • printf("%d %d %d\n", some_int, some_int, some_int);
  • printf("%c\n" a_character);
  • printf("%s%s\n", a_string, a_struct_requiring_its_own_printf_function);

推荐答案

C语言是一种静态类型语言。它没有运行时反射的其他语言做的权力。它也没有提供如何建立与运行时提供任意类型的函数调用。你需要有知道什么 is_odd 的函数签名是多少参数,它接受什么类型的参数是一些方式。它甚至不知道什么时候已经达到了...参数列表的末尾;你需要一个明确的终止。

The C language is a statically-typed language. It does not have the powers of runtime reflection that other languages do. It also does not provide ways to build arbitrary function calls from runtime-provided types. You need to have some way of knowing what the function signature of is_odd is and how many parameter it accepts and what the types of those parameters is. It doesn't even know when it has reached the end of the ... argument list; you need an explicit terminator.

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 ...
    }
}

您的问题是,快速检查的目的是要充分利用JavaScript的高动态可编程的,东西从C丢失。

Your problem is that QuickCheck was designed to take advantage of JavaScripts high dynamic programmability, something missing from C.

更新如果您允许任意函数签名,那么你就需要一种方法来使其再次静态的,也就是说,通过使主叫方提供相应的适配器。

Update If you allow arbitrary function signatures, then you need a way to make it static again, say, by making the caller provide the appropriate adapters.

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);



}

这篇关于我们如何申请过的va_list非可变参数的功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆