我有一个函数可以对结构的指针列表进行排序(省略了实现):
void sort_by(struct thing **start, int size,
int (*cmp_by)(struct thing *, struct thing *));
此函数允许我传入一个比较函数cmp_by
,该函数采用两个结构并根据需要返回1
,0
,-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
代码到其中),如何重写以消除嵌套函数?最好避免复制/粘贴作为解决方案,因为这个代码库在其他地方涉及这个嵌套函数模式。
答案 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
的那个。