Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Generic programming in C.

Reply
Thread Tools

Generic programming in C.

 
 
jacob navia
Guest
Posts: n/a
 
      05-18-2012
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
 
Reply With Quote
 
 
 
 
Rui Maciel
Guest
Posts: n/a
 
      05-18-2012
jacob navia wrote:

> What do you think?


Is the programmer forced to write a pair of source files for each data type
used in a list? And what happens when a programmer must use lists of
different data types in the same source file?


Rui Maciel
 
Reply With Quote
 
 
 
 
jacob navia
Guest
Posts: n/a
 
      05-18-2012
Le 18/05/12 14:51, Rui Maciel a écrit :
> jacob navia wrote:
>
>> What do you think?

>
> Is the programmer forced to write a pair of source files for each data type
> used in a list? And what happens when a programmer must use lists of
> different data types in the same source file?
>
>
> Rui Maciel


The programmer is not "forced " to do anything. He is a free man and can
decide:

1) Use the generic interface with void pointers.
2) Use the generic interface with a special file for each type.
3) Abandon C and use C#

Note that solution (2) means he has to add the resulting object file to
a private library for the application where all those classes for
all the types are stored.

For instance in the Mac he would have to write

mycontainers.a: intList.c
gcc -c -Os intlist.c
ar -r mycontainers.a intlist.o

or something similar.


> And what happens when a programmer must use lists of
> different data types in the same source file?


Nothing. He just includes the header files for the different types.

But I see where you want to go:

Yes, I know. C++ is the best invention since sliced bread. I know.
 
Reply With Quote
 
BGB
Guest
Posts: n/a
 
      05-18-2012
On 5/18/2012 4:14 AM, jacob navia wrote:
> 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?
>


I once did vaguely similar using an extended preprocessor and block macros.

#defmacro FOO(type)
....
lots of stuff...
....
#endmacro

....

FOO(int)

the block-macro differed from #define mostly in that it could handle
larger globs of code and didn't need endless '\' characters.

there were lots of other features as well (such as delayed preprocessor
commands, ...).

IMO, it is a little nicer, but didn't really get lots of use since it is
an extra hassle to set up code to be passed through an extra tool prior
to compilation (unless it stood between make and the compiler or
something, which it didn't do).


otherwise:
passing parameters into specialized header files via #define is a trick
I have used before. it works I guess.

a particular example is this of the "main loop" stub for my 3D engine,
where due to technical reasons I ended up having to "hijack" main (or
WinMain), and a special header generates the main loop.

parameters are used for, among other things, setting GC options (initial
heap-size limits, ...) and indicating which functions to call (functions
are called at various locations in order to do whatever, such as set-up
or tear-down app, redraw the window, ...).


or such...

 
Reply With Quote
 
Ike Naar
Guest
Posts: n/a
 
      05-18-2012
On 2012-05-18, jacob navia <> wrote:
> -------------------------------using specialized list container
> #include "containers.h"


Is this necessary, given that intlist.h includes containers.h ?

> #include "intlist.h"
> static int PrintInt(int data,void *extraArgs)
> {
> fprintf(extraArgs,"%d ",data);


Nit: PrintInt promises to return an int, but fails to do so.

> }
> 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.


There is no need to supply the size of the data type to
iintList.Create(), because the function knows (or at least should now)
that the value must be sizeof(int).
The user is forced to specify a value: if the correct value is passed
it offers no new information to the function, if a wrong value is passed
it may lead to subtle runtime errors. Nonzero cost, zero benefit.

You say you want to avoid code bloat, but as far as I can tell, a
parameterless iintList.Create() needs to be no more than a minimal
wrapper around the generic iList.Create(),

intList *iintList.Create(void) { return iList.Create(sizeof(int)); }

That's not much code bloat.
 
Reply With Quote
 
Rui Maciel
Guest
Posts: n/a
 
      05-18-2012
jacob navia wrote:

> The programmer is not "forced " to do anything. He is a free man and can
> decide:
>
> 1) Use the generic interface with void pointers.
> 2) Use the generic interface with a special file for each type.
> 3) Abandon C and use C#
>
> Note that solution (2) means he has to add the resulting object file to
> a private library for the application where all those classes for
> all the types are stored.
>
> For instance in the Mac he would have to write
>
> mycontainers.a: intList.c
> gcc -c -Os intlist.c
> ar -r mycontainers.a intlist.o
>
> or something similar.


So, basically your technique requires the programmer to add a couple source
files for each list that stores a different data type. Is this true?


> > And what happens when a programmer must use lists of
> > different data types in the same source file?

>
> Nothing. He just includes the header files for the different types.


Could you please provide an example where you use, say, 3 of your lists,
with each one handling a different data type?


Rui Maciel
 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      05-18-2012
Le 18/05/12 23:30, Rui Maciel a écrit :
> So, basically your technique requires the programmer to add a couple source
> files for each list that stores a different data type. Is this true?
>
>


Well you can reduce all files to one if you wish:

#include "containers.h"
#undef DATA_TYPE
#define DATA_TYPE int
#include "listgen.h"
#undef DATA_TYPE


#define DATA_TYPE double
#include "listgen.h"
#undef DATA_TYPE

#define DATA_TYPE float
#include "listgen.h"
#undef DATA_TYPE


Lists for strings (wchar_t and plain char) are already provided. I will
deliver the package with all the basic data types already done
(int, double, etc).

But yes, in principmle you have to add those defines


>> > And what happens when a programmer must use lists of
>> > different data types in the same source file?

>>
>> Nothing. He just includes the header files for the different types.

>
> Could you please provide an example where you use, say, 3 of your lists,
> with each one handling a different data type?



#include "containers.h"
#undef DATA_TYPE
#define DATA_TYPE int
#include "listgen.h"
#undef DATA_TYPE


#define DATA_TYPE double
#include "listgen.h"
#undef DATA_TYPE

#define DATA_TYPE longlong
typedef long long longlong;
#include "listgen.h"
#undef DATA_TYPE


int main(void)
{
intList *L;
doubleList *D;
longlongList *LL;

L = intList.Create(sizeof(int))
D = doubleList.Create(sizeof(double));
LL = longlongList.Create(sizeof(longlong));

doubleList.Add(D,3.141592653);
longlongList.Add(LL,0xDEADBEEFULL);
// etc
}

 
Reply With Quote
 
Edward Rutherford
Guest
Posts: n/a
 
      05-19-2012
jacob navia wrote:

> Le 18/05/12 14:51, Rui Maciel a écrit :
>> jacob navia wrote:
>>
>>> What do you think?

>>
>> Is the programmer forced to write a pair of source files for each data
>> type used in a list? And what happens when a programmer must use lists
>> of different data types in the same source file?
>>
>>
>> Rui Maciel

>
> The programmer is not "forced " to do anything. He is a free man


Sorry, but this sort of casual sexism really gets my goat - it
embarrasses our whole discipline.

It's no wonder that so few women pursue careers in software engineering
when this sort of neanderthal attitude is omnipresent, seeking to exclude
them.

Using gender-neutral language costs the author nothing and is simple
politeness.

IMO. YMMV.

//EPR
 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      05-19-2012
On 2012-05-19, Edward Rutherford <> wrote:
> jacob navia wrote:
>
>> Le 18/05/12 14:51, Rui Maciel a écrit :
>>> jacob navia wrote:
>>>
>>>> What do you think?
>>>
>>> Is the programmer forced to write a pair of source files for each data
>>> type used in a list? And what happens when a programmer must use lists
>>> of different data types in the same source file?
>>>
>>>
>>> Rui Maciel

>>
>> The programmer is not "forced " to do anything. He is a free man

>
> Sorry, but this sort of casual sexism really gets my goat - it
> embarrasses our whole discipline.
>
> It's no wonder that so few women pursue careers in software engineering
> when this sort of neanderthal attitude is omnipresent, seeking to exclude
> them.
>
> Using gender-neutral language costs the author nothing and is simple
> politeness.


Very well, let us continue. Where were we?
Ah yes, "He or she is a free man ..."
 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      05-19-2012
Le 19/05/12 08:34, Edward Rutherford a écrit :
>> The programmer is not "forced " to do anything. He is a free man

> Sorry, but this sort of casual sexism really gets my goat - it
> embarrasses our whole discipline.



Look, I am not responsible for the sexism of the english
language. English is not my mother language but I think
that the generic word for human being is "man".

The dictionary says:

man:

1. an adult male person, as distinguished from a boy or a woman.
2.
a member of the species Homo sapiens or all the members of this species
collectively, without regard to sex: prehistoric man.

My mistake would have been that I used the "he" instead of he/she
because I tried to make the "he" compatible with the first
meaning of "man" and not the second.

I agree that there are less women than men in here, for instance
there isn't a single women in this group as far as I know, and
that this situation is bad.

In any case no sexism was intended.

jacob
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
not just generic type programming,but also parallism generic syntaxprogramming?? minlearn C++ 2 03-13-2009 05:17 PM
generic interfaces with generic methods Murat Tasan Java 1 02-03-2009 12:17 PM
Generic class in a non generic class nramnath@gmail.com Java 2 07-04-2006 07:24 AM
Java Generic programming using subclassing Paul O'Grady Java 19 02-18-2005 10:39 PM
What happened to Generic Programming in Java? Hung Jung Lu Java 6 11-18-2003 02:37 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57