如何删除此(不可移植)嵌套函数?

时间:2014-04-29 17:02:22

标签: c gcc function-pointers

我有一个函数可以对结构的指针列表进行排序(省略了实现):

void sort_by(struct thing **start, int size,
    int (*cmp_by)(struct thing *, struct thing *));

此函数允许我传入一个比较函数cmp_by,该函数采用两个结构并根据需要返回10-1。然后存在这个(仅限GCC!)函数:

void reverse_by(struct thing **start, int size,
        int (*cmp_by)(struct thing *, struct thing *)) {

    int cmp_reverse(struct thing *a, struct thing *b) {
        return -cmp_by(a, b);
    }

    sort_by(start, size, cmp_reverse);
}

此函数采用与sort_by相同的参数,但通过翻转比较结果的符号来反转排序顺序。 GCC具有此扩展以允许嵌套函数。如何reverse_by便携式编写?即使我尝试将其付诸实践,也无法进行编译:

int (*reverse(int (*fn)(struct thing *, struct thing *)))(struct thing *, struct thing *) {
    return -fn;  /* OBVIOUSLY AND CONCEPTUALLY WRONG */
}
int (*reverse(int (*fn)(struct thing *a, struct thing *b)))(struct thing *x, struct thing *y) {
    return -fn(a, b);  /* WRONG RETURN TYPE WRONG WRONG */
}
int (*reverse(int (*fn)(struct thing *a, struct thing *b)))(struct thing *x, struct thing *y) {
    return -fn(x, y);  /* YOU HAVE NO IDEA WHAT YOU'RE DOING STOP GUESSING */
}

没有添加大量额外的结构部分或重写代码行调用reverse_by(或复制粘贴sort_by代码到其中),如何重写以消除嵌套函数?最好避免复制/粘贴作为解决方案,因为这个代码库在其他地方涉及这个嵌套函数模式。

1 个答案:

答案 0 :(得分:1)

可重入但不是线程安全的解决方案:

typedef int (*cmp_func)(struct thing *, struct thing *);

static cmp_func reverse_cmp_by_impl;

static int cmp_reverse(struct thing *a, struct thing *b) {
    int ret;
    cmp_func impl = reverse_cmp_by_impl;
    ret = -impl(a, b);
    reverse_cmp_by_impl = impl; // For re-entrancy
    return ret;
}

void reverse_by(struct thing **start, int size, cmp_func cmp_by) {
    reverse_cmp_by_impl = cmp_by;
    sort_by(start, size, cmp_reverse);
}

请注意,这是假设sort_by的合理实施。即除了可能通过比较函数之外,不以任何方式调用reverse_by的那个。