Generic programming in C.



When I presented an example of the interface here (thread CCL vs STL, a comparison), many posters complained about the syntax:

int main(void)
{
List *L;
int data;

L = iList.Create(sizeof(int));

data = 0;
iList.Add(L,&data);
iList.PushFront(L,&data);
data = 2;
iList.InsertAt(L,1,&data);
// ...
}

It was said that passing a void pointer couldn't be checked by
the compiler (what is trure of course) and that the whole wasn't
very easy to use (maybe).

I have developed a "generic" approach using a parametized file.

For instance, if you want a list of integers, you write a small file
like this:

---------------------------intlist.c (the implementation)
#include "containers.h"
#undef DATA_TYPE
#define DATA_TYPE int
#include "listgen.c"
#undef DATA_TYPE

----------------------------intlist.h (the declarations)
#include "containers.h"
#undef DATA_TYPE
#define DATA_TYPE int
#include "listgen.h"
#undef DATA_TYPE

That's all. This defines following stuff:

A type called "intList" that implements ALL the functions
of the list container for the int data type. The requirements
for the data type are that it must be a value type, i.e. the
code assumes that it is passed by value. At the same time
the "iintList" interface is defined with the same entry
points as the generic list interface iList.

Besides it must be a single token, for instance for using
long long you must

typedef long long longlong;
#define DATA_TYPE longlong

Besides those two points, the file allows now to do as follows:

-------------------------------using specialized list container
#include "containers.h"
#include "intlist.h"
static int PrintInt(int data,void *extraArgs)
{
fprintf(extraArgs,"%d ",data);
}
int main(void)
{
intList *L;
int data;

L = iintList.Create(sizeof(int));
iintList.Add(L,0);
iintList.PushFront(L,0);
iintList.InsertAt(L,1,2);

iintList.Add(L,5);

iintList.Add(L,6);
iintList.Apply(L,PrintInt,stdout);
iintList.Finalize(L);
}

Note that the "Create" function still takes the same
arguments as the original generic one. I want to keep
all code compatible since it would be better to avoid code bloat.

Each instanstiated type adds 18.6K to the program (x86+gcc/OS X Mac)

If you have several types, code could be shared in many instances
since the data type remains compatible, and the signatures weren't
changed.

For the time being code is NOT shared.


What do you think?

jacob
.



Relevant Pages

  • RFC: if_clone overhaul
    ... Please test/review the following patch to the network interface cloneing ... static void ... -if_clone_lookup(const char *name, int *unitp) ... static int gifmodevent; ...
    (freebsd-net)
  • Re: Wikipedia vandalism
    ... to int main. ... the interface between something and an C program. ... supplied it on the "stack" with which people with a clue know about. ... worse (continued execution based on garbage results). ...
    (comp.lang.c)
  • [PATCH 3/7] adding xc5000 tuner chip driver
    ... this code also uses the tunerchip.h interface which allows to attach ... It uses the latest Xceive reference driver which fixes some issues. ... new file mode 100644 ... unsigned int frequency; ...
    (Linux-Kernel)
  • [PATCH] usbmon: add binary interface
    ... USB records are stored in a liked list, alike current text interface implementation, so most code is shared from binary and text interface. ... unsigned int cmd, unsigned long arg) ... struct urb *urb, char ev_type) ...
    (Linux-Kernel)
  • Re: Possible to pass strings back to ASP from ActriveX?
    ... afx_msg int AboutBox; ... helpstring("AxTemplateTest1 ActiveX Control module"), ... // Primary dispatch interface for CAxTemplateTest1Ctrl ... helpstring("Dispatch interface for AxTemplateTest1 Control")] ...
    (microsoft.public.windowsce.embedded)