This is a good example. Without trampolines, this could look like this (Godbolt: https://godbolt.org/z/nK5fqMxjs).
int main() {
struct Point {
int x, y;
} points[3] = {
{ 3, 1 },
{ 2, 2 },
{ 5, 7 }
};
struct Point target = { 4, 5 };
long dsq(const struct Point *p) {
long dx = p->x - target.x, dy = p->y - target.y;
return dx*dx + dy*dy;
}
typedef typeof(dsq) dsq_f;
int compare(const void *p, const void *q, void *data) {
wide(dsq_f) *dsq = data;
long a = CALL(*dsq, (p)), b = CALL(*dsq, (q));
return (a > b) - (a < b);
}
qsort_r(points, 3, sizeof(struct Point), compare, &CLOSURE(dsq_f, dsq));
for (int i = 0; i < 3; ++i)
printf("%d,%d\n", points[i].x, points[i].y);
}
There are slightly different ways how to define the helper macros, I am still experimenting a bit. Here you could avoid the typedef if defined differently. But ideally, there would be native language support that avoids these macros.