3

I've developed a C dll containing simple link list functions but they all are defined on int type i.e. when ever the user will create a link list using my library he can only created a list of ints.So what if I could do something(except void*) to let the user create a list of arbitrary data types say char,float or even user define struct?That too without recompilation.

thanks.

rsjethani
  • 2,179
  • 6
  • 24
  • 30
  • 1
    Note that if you have your implementation hidden inside a pre-compiled library, even C++ wouldn't help you here. In general, C++ templates need to live in header files. – Oliver Charlesworth Jun 24 '11 at 11:34

7 Answers7

3

Using macros is a decent approach to templatizing definitions, i.e. generating any number of definitions based on a pattern. Here is an example -- but it is ugly as hell.

#include <stdlib.h>

#define template_struct_A(T1,T2) struct A_ ## T1 ## _ ## T2 { \
    T1 a; \
    T2 b; \
}
#define struct_A(T1,T2) struct A_ ## T1 ## _ ## T2

struct C { const char*s; };

typedef const char* pchar;
template_struct_A(int, pchar); // explicit instantiation of struct A<int, pchar>

int main() {
    struct X { struct C x; } x;
    struct_A(int, pchar) o1; // struct A<int, const char*> o1
    o1.a = 1;
    o1.b = "hello";

    struct_A(int, pchar) o2; // struct A<int, const char*> o2
    o2.a = o1.a * 2;
    o2.b = "world";

    typedef struct_A(int, pchar)* pAInt;
    typedef struct C structC;
    template_struct_A(pAInt, structC) o3; // struct A<struct A<int, const char*>, struct C> o3
    o3.a = &o2;
    o3.b.s =  "hi";

    printf ("o1.a = %d, o1.b = %s, o2.a = %d, o2.b = %s, o3.b.s = %s\n", o1.a, o1.b, o2.a, o2.b, o3.b.s);
}
Nick
  • 5,765
  • 5
  • 27
  • 36
1

The only option, apart from void * is, well, nothing.

The only option is void *, is what I'm saying.

void * is the only generic type in C; and to a degree, also the only generic degree in C++; as neither are what you would call dynamic languages.

Of course, if you were feeling particularly crazy, you could readjust your internal struct for linked list links to include a union, and have a series of functions named as

add_<type>_to_list(); // <type> = char, int, float…

But that's not likely to give satisfactory results.

Williham Totland
  • 28,471
  • 6
  • 52
  • 68
1

Language/Compiler Support

Examples

Community
  • 1
  • 1
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
  • I'm not entirely sure; but it looks as if both of these are *compile*-time features; not actually useful at runtime. – Williham Totland Jun 24 '11 at 11:41
  • @Williham Totland: Ughh, that's C. Any runtime support and you can forget identifying `int` unless you're annotating some integer type implementing all the necessary hooks for the runtime. You can only do it via compile time. – Matt Joiner Jun 24 '11 at 11:46
  • @Williham: If haskell is anything to show, theres a heck of alot to you can do with some compile-time generics. If you combine Nik's example of macros to enstantiate existential datastructures over types(smelling a bit like OCaml functors), then overload their common operations with a _generic statement, you're on your way down a dynamic-fealing road. – Eli Feb 08 '12 at 06:41
1

I agree with the other answers that void * is the only way to go. But you can squeeze more dynamic behavior without recompiling if you add a size parameter that indicates how many bytes the void * points to.

void *shift(list *plist, unsigned size);
void unshift(list *plist, void *item, unsigned size);

Then you can hide the size with macros.

#define Cshift(L)   shift(L,sizeof(char))
#define Cunshift(L,I) unshift(L,I,sizeof(char))
luser droog
  • 18,988
  • 3
  • 53
  • 105
0

There is no way to do it at runtime without void *. But there is way to do it without separately compiled code: all operations can be #define.

http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/queue.h?rev=1.75;content-type=text%2Fx-cvsweb-markup

blaze
  • 4,326
  • 18
  • 23
0

You could use macros. For example you can make different list node types, with differently typed data members and keep sure all have a next and prev member. Then just use macros for all the list operations (like add, insert, remove), as these don't care about the type stored.

Of course macros aren't that type safe as templates and are considered "bad style". But hey we're in C, who fears macros in C? And void* isn't that type safe, too.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
0

You could essentially rewrite C++ in C, to whichever level of detail you need. You could start with making the linked list's data type a struct * to some wrapper structure which itself could contain a type identifier and a void pointer to the actual data. You could write your own vtable to allow for polymorphism, and you could add reference counting and memory management... none of that is magic, so if you really need that sort of generality, you could certainly write it all in C. Or just use C++ :-)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084