79280121

Date: 2024-12-14 05:37:20
Score: 1
Natty:
Report link

I learned a lot from the answers, and they are correct. Thanks to those contributing.

The code as shown in question above is not well defined, because void* is "not compatible" with square*, specifically because pointers to struct and non struct types may have different size and representations, as quoted here.

https://stackoverflow.com/a/1241314/1087626

However, as stated in above quote, and confirmed below, all struct types are guaranteed by the standard to have the same size and representation. So all I need to do, is to change void* to obj_* where obj_ is a dummy struct, and the code is supported by the standard.

This falls into the "alternative solutions" category. It's just one line extra for the dummy struct and 2 lines changed for void* => obj_* and in IMO, this is much preferable to my previous solution, which was also discussed in comments above, of having 10x10 wrapper functions to cast the pointers.

Full code shown below:


#include <stdio.h>

// types
typedef struct {
  int a;
  double d;
} circle;

typedef struct {
  int b;
  float f;
} square;

// ... 10 types,.. different sizeof()

// concrete API
int open_circle(circle* c) {
  printf("opening circle: %d: %f\n", c->a, c->d);
  return c->a;
}

int open_square(square* s) {
  printf("opening square: %d: %f\n", s->b, s->f);
  return s->b;
}

int send_circle(circle* c, const char* msg) {
  printf("sending circle: %d: %f: %s\n", c->a, c->d, msg);
  return -c->a;
}

int send_square(square* s, const char* msg) {
  printf("sending square: %d: %f: %s\n", s->b, s->f, msg);
  return -s->b;
}

// ten more operations for each type

typedef struct { int dummy_; } obj_;

// "genericised" function pointer types (note the void* params!!)
typedef int (*open_fpt)(obj_* o);
typedef int (*send_fpt)(obj_* o, const char*);

typedef void (*gfp)(void); // generic function pointer

int generic_processor(void* obj, gfp open, gfp send) {
  int sum = 0;
  sum += ((open_fpt)open)(obj);
  sum += ((send_fpt)send)(obj, "generically sent");
  return sum;
}

int main() {
  circle c = {2, 22.2};
  square s = {3, 33.3F};

  int net = 0;
  net += generic_processor(&c, (gfp)open_circle, (gfp)send_circle);
  net += generic_processor(&s, (gfp)open_square, (gfp)send_square);
  printf("net %d\n", net);
  return 0;
}
Reasons:
  • Blacklisted phrase (0.5): Thanks
  • Blacklisted phrase (0.5): I need
  • Blacklisted phrase (1): stackoverflow
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
Posted by: Oliver Schönrock