1

I'm writing a generic list adt and this is what I have in the header so far. From what I know this is usually how it's done.

typedef struct _node {
    void *data;
    struct _node *next;
} Node;

typedef struct {
    Node *dummy;
    int (*comparePtr) (void *d1, void *d2);
    void (*destroyPtr) (void *data);
} List;

List *ListCreate (int (*comparePtr) (void *d1, void *d2), void (*destroyPtr) (void *data));
void ListDestroy (List *node);
void ListAddToTail (List *list, void *data);
int ListContains (List *list, void *data);
void *ListGetFromIndex (List *list, int index);

It works fine on the implementation side. What I noticed is that in order to use this adt to store integers I have to make calls in this fashion

int a = 5;
ListAddToTail (list, &a);

whereas in a perfect world I'd be able to do this

ListAddToTail (list, 55);

So the question is is it possible to modify this to allow me to pass in any type of data, pointer or non-pointer, non-pointer being mainly primitive types like integers and characters?

TreeTree
  • 3,200
  • 3
  • 27
  • 39
  • I don't know of a way to do it in C, except maybe some evil preprocessor abuse. In C++, you could use templates, but that doesn't answer your question of course.. – lethal-guitar Jan 15 '13 at 21:29
  • Yea, I can't think of a way without modifying the prototype to accept an integer type but that's not generic at all. The only thing that's bothering me about this is that in order to use this list I have to pass the pointer to the data that I want to store. So a list of integers is technically a list of pointers to integers. – TreeTree Jan 15 '13 at 21:33
  • Maybe this question also gives you some ideas: http://stackoverflow.com/questions/1899906/genericity-vs-type-safety-using-void-in-c – lethal-guitar Jan 15 '13 at 21:37

1 Answers1

3

There's no clean, completely nice way to solve this. You have a few options:

  • On most platforms you can simply get away with stuffing an integer in a void *. It's messy but it works pretty well, especially if you silence the warnings

  • Define your own boxing functions / macros that allocate the required space and give you back a pointer. You can probably make a really nice macro using typeof tricks. But then you have to remember to free that space

The main issue should be uniformity. Your list lets people store pointers. You should let them deal with questions like "how do I get a pointer to my data".


EDIT

I just made a primitive "box" macro:

#define box(value)                              \
({                                              \
    typeof(value) *ptr = malloc(sizeof *ptr);   \
    *ptr = value;                               \
    ptr;                                        \
})
Community
  • 1
  • 1
cnicutar
  • 178,505
  • 25
  • 365
  • 392