Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Generic programming in C

11 views
Skip to first unread message

jacob navia

unread,
Apr 17, 2010, 4:31:29 AM4/17/10
to
This is a message about programming in C. It is not:

(1) about Schildt
(2) about the errors of Mr Cunningham
(3) Some homework, even if it was made at home and it was surely a lot
of work.

Building generic components
---------------------------
If you take the source code of a container like “arraylist”, for
instance, you will notice that all those “void *”are actually a single
type, i.e. the type of the objects being stored in the container. All
generic containers use “void *” as the type under which the objects are
stored so that the same code works with many different types.

Obviously another way is possible. You could actually replace the object
type within that code and build a family of functions and types that can
be specialized by its type parameter. For instance:

struct tag$(TYPE)ArrayInterface;
typedef struct _$(TYPE)Array {
struct tag$(TYPE)ArrayInterface *VTable;
size_t count;
unsigned int Flags;
$(TYPE) *contents;
size_t capacity;
size_t ElementSize;
unsigned timestamp;
CompareFunction CompareFn;
ErrorFunction RaiseError;
} $(TYPE)_Array ;

Now, if we just substitute $(TYPE) with “double” in the code above, we
obtain:

struct tagdoubleArrayInterface;
typedef struct _doubleArray {
struct tagdoubleArrayInterface *VTable;
size_t count;
unsigned int Flags;
double *contents;
size_t capacity;
size_t ElementSize;
unsigned timestamp;
CompareFunction CompareFn;
ErrorFunction RaiseError;
} double_Array ;

We use the name of the parameter to build a family of names, and we use
the name of the type parameter to declare an array of elements of that
specific type as the contents of the array. This double usage allows us
to build different name spaces for each different array type, so that we
can declare arrays of different types without problems.

Using the same pattern, we can build a family of functions for this
container that is specialized to a concrete type of element. For
instance we can write:

static int RemoveAt($(TYPE)_Array *AL,size_t idx)
{
$(TYPE) *p;
if (idx >= AL->count)
return CONTAINER_ERROR_INDEX;
if (AL->Flags & AL_READONLY)
return CONTAINER_ERROR_READONLY;
if (AL->count == 0)
return -2;
p = AL->contents+idx;
if (idx < (AL->count-1)) {
memmove(p,p+1,(AL->count-idx)*sizeof($(TYPE)));
}
AL->count--;
AL->timestamp++;
return AL->count;
}

when transformed, the function above becomes:

static int RemoveAt(double_Array *AL,size_t idx)
{
double *p;
if (idx >= AL->count)
return CONTAINER_ERROR_INDEX;
if (AL->Flags & AL_READONLY)
return CONTAINER_ERROR_READONLY;
if (AL->count == 0)
return -2;
p = AL->contents+idx;
if (idx < (AL->count-1)) {
memmove(p,p+1,(AL->count-idx)*sizeof(double));
}
AL->count--;
AL->timestamp++;
return AL->count;
}

Now we can build a simple program in C that will do the substitution
work for us. To make things easier, that program should build two files:
1.The header file, that will contain the type definitions for our array.
2.The C source file, containing all the parametrized function definitions.
We separate the commands to change the name of the file from the rest of
the text by introducing in the first positions of a line a sequence of
three or more @ signs. Normally we will have two of those “commands”:
one for the header file, another for the c file.

Besides that, our program is just a plain text substitution. No parsing,
nor anything else is required. If we write “$(TYPE)” within a comment or
a character string, it will be changed too.

#include <stdlib.h>
#include <string.h>

#define MAXLINE_LEN 2048
#define MAX_FNAME 1024
#define EXPANSION_LENGTH 256

int main(int argc,char *argv[])
{
FILE *input,*output=NULL;
char buf[MAXLINE_LEN],
tmpLine[MAXLINE_LEN+EXPANSION_LENGTH];
char tmpBuf[MAX_FNAME];
char outputFile[MAX_FNAME];
char *TypeDefinition;
unsigned lineno = 1;

if (argc < 3) {
fprintf(stderr,
"Usage: %s <template file to expand> <type name>\n",
argv[0]);
return EXIT_FAILURE;
}
input = fopen(argv[1],"r");
if (input == NULL) {
fprintf(stderr,"Unable to open file '%s'\n",argv[1]);
return EXIT_FAILURE;
}
TypeDefinition = argv[2];
delta = strlen(TypeDefinition) - strlen("$(TYPE)");
while (fgets(buf,sizeof(buf)-1,input)) {
if (buf[0]=='@' && buf[1] == '@' && buf[2] == '@') {
int i=0,j=0;
while (buf[i] == '@')
i++;
while (buf[i] != 0 &&
buf[i] != '\n' &&
i < MAX_FNAME-1) {
tmpBuf[j++] = buf[i];
i++;
}
tmpBuf[i] = 0;
strrepl(tmpBuf,"$(TYPE)",TypeDefinition,outputFile);
if (output != NULL)
fclose(output);
output = fopen(outputFile,"w");
if (output == NULL) {
fprintf(stderr,
"Impossible to open '%s'\n",outputFile);
return(EXIT_FAILURE);
}
}
else if (lineno == 1) {
fprintf(stderr,
"Error: First line should contain the file name\n");
exit(EXIT_FAILURE);
}
else {
/* Normal lines here */
if (strrepl(buf,"$(TYPE)",TypeDefinition,NULL)
>= sizeof(tmpLine)) {
fprintf(stderr,
"Line buffer overflow line %d\n",lineno);
break;
}
strrepl(buf,"$(TYPE)",TypeDefinition,tmpLine);
fwrite(tmpLine,1,strlen(tmpLine),output);
}
lineno++;
}
fclose(input);
fclose(output);
return EXIT_SUCCESS;
}

The heart of this program is the “strrepl” function that replaces a
given character string in a piece of text. If you call it with a NULL
output parameter, it will return the number of characters that the
replacement would need if any. For completeness, here is the code for
strrepl:

int strrepl(char *InputString,
char *StringToFind,
char *StringToReplace,
char *output)
{
char *offset = NULL, *CurrentPointer = NULL;
int insertlen;
int findlen = strlen(StringToFind);
int result = 0;

if (StringToReplace)
insertlen = strlen(StringToReplace);
else
insertlen = 0;
if (output) {
if (output != InputString)
memmove(output,InputString,strlen(InputString)+1);
InputString = output;
}
else
result = strlen(InputString)+1;

while (*InputString) {
offset = strstr (!offset ? InputString : CurrentPointer,
StringToFind);
if (offset == NULL)
break;
CurrentPointer = (offset + (output ? insertlen : findlen));
if (output) {
strcpy (offset, (offset + findlen));
memmove (offset + insertlen,
offset, strlen (offset) + 1);
if (insertlen)
memcpy (offset, StringToReplace, insertlen);
result++;
}
else {
result -= findlen;
result += insertlen;
}
}
return result;
}

And now we are done. The usage of this program is very simple:
expand <template file> <type name>

For instance to substitute by “double” in the template file
“arraylist.tpl” we would use:

expand arraylist.tpl double

We would obtain doublearray.h and doublearray.c

BUG: Obviously, this supposes that the type name does NOT contain any
spaces. Some type names do contain spaces: long double and long long. If
you want to use those types you should substitute the space with a “_”
for instance, and make a typedef:

typedef long double long_double;

And use that type (“long_double”) as the substitution type.

All container code of the library arrives in two versions:
A library version, that can be used in its generic form.
A "templated" version that can be used to build type specific code.

The reuslts are compatible, i.e. you can start by using the generic
functions of the library and then switch to the type specific ones
without changing your code at all, using only a different constructor
function.

jacob

Gene

unread,
Apr 17, 2010, 1:28:43 PM4/17/10
to

Fine! Some notes:

Generating code from templates like this is pretty standard in larger
code bases. But I've generally seen a short script in a language like
awk or perl used to transform the template instead of C. I think what
you've done in C represents one line of Perl, for example.

You can also accomplish what you've done so far with preprocessor
abuse.

The down side in a big system with either approach will be code
bloat. If your program has a hundred node types, you (at least sans a
very smart linker) end up with a hundred copies of list code that
could equally well be one void* implementation. Other than type
saftey, the other broken part of the void* approach is in the
debugger, where you have to know what a void* is pointing to in order
to see its contents.

Of course you can also use the template technique to create endogenous
data structures (your examples are exogenous).

Here is a preprocessor interface for dynamically sized endogenous
array package:

/*
dyanamic arrays in C (through preprocessor abuse)

parameters:

ELEMENT_TYPE - type of elements of dynamic array to be declared
NAME - base name used in constructor, destructor, and accessor
functions
ELTS - field name of C array of elements inside the dynamic array
struct
N_ELTS - field name for fill pointer, current number of valid
elements

structure:

a dynamic array is a struct with the following fields:

current_size - the number of array elements currently allocated to
the array

N_ELTS - a "fill pointer" that tracks the number of elements that
have been
pushed onto the array so far; push()ing grows the array
automatically

ELTS - a pointer to ELEMENT_TYPE with specified name; these are
the
array elements

an example

// ---- in foo.h ----

// we need a dynamic array of these things
typedef struct foo_t {
char *name;
int count;
} FOO;

// create the typedef for the type FOO_ARRAY
TYPEDEF_DYNAMIC_ARRAY(FOO_ARRAY, FOO, foo_list, val, n_vals) // no
semicolons!

// do the prototypes for the constructor, destructor, and accessor
functions
DECLARE_DYNAMIC_ARRAY_PROTOS(FOO_ARRAY, FOO, foo_list, val,
n_vals)

// ---- in foo.c ----

// create the bodies for the constructor, destructor, and accessor
functions
DECLARE_DYNAMIC_ARRAY_FUNCS(FOO_ARRAY, FOO, foo_list, val, n_vals)

// use all the new stuff!
void do_stuff_with_foos(void)
{
int i;
char buf[100];
FOO_ARRAY list[1]; // or FOO_ARRAY list; but then we're forever
&'ing
FOO_ARRAY copy[1];

init_foo_list(list); // do this JUST ONCE right after
declaration
init_foo_list(copy); // (not necessary for static/global
decls)

setup_foo_list(list, 10); // allow for 10 elements

// read some data and push it on the list tail
while (scanf("%d %s", &i, buf) == 2) {
// get pointer to new (empty) element at the end of array
FOO *p = pushed_foo_list_val(list);
// fill in field values
p->name = safe_strdup(buf);
p->count = i;
}

// shows safe and unsafe access to elements
printf("forward listing:\n");
for (i = 0; i < list->n_val; i++)
printf("name=%s count=%d (%d)\n",
list->val[i].name, // fast unsafe access
foo_list_val_ptr(list, i)->count, // slower safe pointer
access
foo_list_val(list, i).count); // copying access

copy_foo_list_filled(copy, list); // copies only filled
elements

// print in reverse order by popping from tail
printf("backward listing:\n");
while (copy->n_val > 0) {
FOO *p = popped_foo_list_val(copy);
printf("name=%s count=%d\n", p->name, p->count);
}

// clear out all the allocated storage for the ilst
clear_foo_list(list);
clear_foo_list(copy);
}

notes on the example:

* NAME (foo_list) must be unique in the namespace to avoid
collisions

* ELTS need not be unique

* the declaration FOO_ARRAY list[1]; is an idiom that avoids lots of
&'s
in the rest of the code; feel free to use FOO_ARRAY list; if you
like &'s

* init_foo_list() is not needed on static or global declarations
because
it merely sets things to zero

* the call pushed_foo_list_val() grows the list automatically to
accomodate
more than 10 elements; arrays grow (never shrink) until they are
clear()ed;
the fill pointer is foo_list->n_val

* safe copying access is good for reading small elements; pointer
access is
for writing elements and for reading within large struct elements

* copy_foo_list_filled() copies only n_val elements after ensuring
there is
enough space in the destination; copy_foo_list() does the same
thing
for all current_size elements; it ignores the fill pointer except
to copy
its value

*/


BGB / cr88192

unread,
Apr 17, 2010, 10:24:36 PM4/17/10
to

"jacob navia" <ja...@spamsink.net> wrote in message
news:hqbrkv$p15$1...@speranza.aioe.org...

snip...


for the preprocessor for my assembler (based on my C preprocessor), I added
a few features:
block-macros, which are basically like the normal macros but which can deal
with multiple lines, and including embedded preprocessor commands (the
contents of the macro can be controlled by PP-directives);
"delayed" preprocessor commands, which may not be handled until after the
macro is expanded, or even delayed through multiple levels of expansion;
ability to support multiple levels of scoping;
...

but, yes, similar additions could be made to another C-style preprocessor,
which could allow more complex macro expansion without having to switch to
some alternative syntax.


or such...


jacob navia

unread,
Apr 19, 2010, 3:17:07 AM4/19/10
to
Gene a �crit :

> Fine! Some notes:
>
> Generating code from templates like this is pretty standard in larger
> code bases. But I've generally seen a short script in a language like
> awk or perl used to transform the template instead of C. I think what
> you've done in C represents one line of Perl, for example.
>

I do not think so, if you look carefully at the code you will see that
it does more than what you believe. And in any case, I do not want to
force the users of the library to install another programming language
and all the associated hassle...

> You can also accomplish what you've done so far with preprocessor
> abuse.
>

No. I can't because lines like

#include "mytypedef.h"

could NOT be included in the resulting C code. My goal is that the C
code remains perfectly lisible and maintainable independently of the
template expansor, i.e. I do not want macros expanded or comments
stripped out, etc. Besides, I do want to replace $(TYPE) within the
comments!

> The down side in a big system with either approach will be code
> bloat.

This is always the case for templates. You can, however, compile all
those expanded templates into a library, and the linker will pukll out
of that library only those files that are effectively used. The code
bloat of the template for the flexible array container is just 2.3K

If your program has a hundred node types, you (at least sans a
> very smart linker) end up with a hundred copies of list code that
> could equally well be one void* implementation.

If you do not want those templates you can use the void * implementation
of the library. The only advantage of the templated version is that it
allows many optimizations and calculations to be done at compile time
instead of run time.


> Other than type
> saftey, the other broken part of the void* approach is in the
> debugger, where you have to know what a void* is pointing to in order
> to see its contents.
>

Yes, but I hope your debugger allows to make a cast.


Your code is interesting, but it would be more interesting if you would
give an actual example of how it works. Those macros aren't defined
somewhere.

Thanks for your answer, and sorry for the delay to answer.

jacob

Ben Bacarisse

unread,
Apr 19, 2010, 8:06:01 AM4/19/10
to
jacob navia <ja...@spamsink.net> writes:

> This is a message about programming in C. It is not:
>
> (1) about Schildt

Although there is a connection.

> (2) about the errors of Mr Cunningham
> (3) Some homework, even if it was made at home and it was surely a lot
> of work.

<snip>


> Now we can build a simple program in C that will do the substitution
> work for us. To make things easier, that program should build two
> files:
> 1.The header file, that will contain the type definitions for our array.
> 2.The C source file, containing all the parametrized function definitions.
> We separate the commands to change the name of the file from the rest
> of the text by introducing in the first positions of a line a sequence
> of three or more @ signs. Normally we will have two of those
> “commands”: one for the header file, another for the c file.

I am not a fan of this sort of interface. I would prefer not to have
the target file name embedded in the source. I would go for a method
that integrates better with tools like make where by the output file is
determined by the program's command line. A switch (and maybe some
extra help in the source file) would then determine whether a .h or .c
was output.

> Besides that, our program is just a plain text substitution. No
> parsing, nor anything else is required. If we write “$(TYPE)” within a
> comment or a character string, it will be changed too.
>
> #include <stdlib.h>
> #include <string.h>

missing #include <stdio.h>

> #define MAXLINE_LEN 2048
> #define MAX_FNAME 1024
> #define EXPANSION_LENGTH 256
>
> int main(int argc,char *argv[])
> {
> FILE *input,*output=NULL;
> char buf[MAXLINE_LEN],
> tmpLine[MAXLINE_LEN+EXPANSION_LENGTH];
> char tmpBuf[MAX_FNAME];
> char outputFile[MAX_FNAME];
> char *TypeDefinition;
> unsigned lineno = 1;
>
> if (argc < 3) {
> fprintf(stderr,
> "Usage: %s <template file to expand> <type name>\n",
> argv[0]);
> return EXIT_FAILURE;
> }
> input = fopen(argv[1],"r");
> if (input == NULL) {
> fprintf(stderr,"Unable to open file '%s'\n",argv[1]);
> return EXIT_FAILURE;
> }
> TypeDefinition = argv[2];
> delta = strlen(TypeDefinition) - strlen("$(TYPE)");

delta is not declared.

> while (fgets(buf,sizeof(buf)-1,input)) {

why -1? (Schildt does this in some of his fgets examples.)

> if (buf[0]=='@' && buf[1] == '@' && buf[2] == '@') {
> int i=0,j=0;
> while (buf[i] == '@')
> i++;
> while (buf[i] != 0 &&
> buf[i] != '\n' &&
> i < MAX_FNAME-1) {

I think you intended to test j here.

> tmpBuf[j++] = buf[i];
> i++;
> }
> tmpBuf[i] = 0;

Again, j is probably what you mean. As you have it, tmpBuf may not be a
proper string and the assignment might even be off the end of the array.

> strrepl(tmpBuf,"$(TYPE)",TypeDefinition,outputFile);

strrepl can't tell whether there is room -- that's why you do a "dry
run" in the main code below. Surely you need to do that here also?

> if (output != NULL)
> fclose(output);
> output = fopen(outputFile,"w");

This is dangerous. If the loop above cut the filename short, this fopen
could destroy an unintended file.

> if (output == NULL) {
> fprintf(stderr,
> "Impossible to open '%s'\n",outputFile);
> return(EXIT_FAILURE);
> }
> }
> else if (lineno == 1) {
> fprintf(stderr,
> "Error: First line should contain the file name\n");
> exit(EXIT_FAILURE);
> }
> else {
> /* Normal lines here */
> if (strrepl(buf,"$(TYPE)",TypeDefinition,NULL)
> >= sizeof(tmpLine)) {
> fprintf(stderr,
> "Line buffer overflow line %d\n",lineno);
> break;
> }
> strrepl(buf,"$(TYPE)",TypeDefinition,tmpLine);

I think "$(TYPE)" deserves a #define. You use it four times.

> fwrite(tmpLine,1,strlen(tmpLine),output);

why not fputs?

This indentation is likely to confuse the reader. This else belongs to
"if (output)".

> while (*InputString) {
> offset = strstr (!offset ? InputString : CurrentPointer,
> StringToFind);
> if (offset == NULL)
> break;
> CurrentPointer = (offset + (output ? insertlen : findlen));
> if (output) {
> strcpy (offset, (offset + findlen));

Undefined behaviour since the source and destination overlap.

> memmove (offset + insertlen,
> offset, strlen (offset) + 1);
> if (insertlen)
> memcpy (offset, StringToReplace, insertlen);
> result++;
> }
> else {
> result -= findlen;
> result += insertlen;
> }
> }
> return result;
> }

I don't like the fact that the returned result is different when output
is or is not NULL. Your text describes one half of this behaviour, but
not the other. I'd make it always return the number of characters
needed or actually written.

> And now we are done. The usage of this program is very simple:
> expand <template file> <type name>
>
> For instance to substitute by “double” in the template file
> “arraylist.tpl” we would use:
>
> expand arraylist.tpl double
>
> We would obtain doublearray.h and doublearray.c
>
> BUG: Obviously, this supposes that the type name does NOT contain any
> spaces. Some type names do contain spaces: long double and long
> long. If you want to use those types you should substitute the space
> with a “_” for instance, and make a typedef:
>
> typedef long double long_double;
>
> And use that type (“long_double”) as the substitution type.

It also supposes that the type can be used in that same syntactic
position as a plain old type like int. There are therefore other cases
where a typedef is needed.

<snip>
--
Ben.

Michael Foukarakis

unread,
Apr 19, 2010, 9:41:01 AM4/19/10
to
On Apr 19, 10:17 am, jacob navia <ja...@spamsink.net> wrote:
> Gene a crit :

>
> > Fine!  Some notes:
>
> > Generating code from templates like this is pretty standard in larger
> > code bases. But I've generally seen a short script in a language like
> > awk or perl used to transform the template instead of C.  I think what
> > you've done in C represents one line of Perl, for example.
>
> I do not think so, if you look carefully at the code you will see that
> it does more than what you believe. And in any case, I do not want to
> force the users of the library to install another programming language
> and all the associated hassle...

Nobody relies on one programming language for everything. If one
doesn't know sed/awk, (s)he's doomed anyway.


> > The down side in a big system with either approach will be code
> > bloat.
>
> This is always the case for templates. You can, however, compile all
> those expanded templates into a library, and the linker will pukll out
> of that library only those files that are effectively used. The code
> bloat of the template for the flexible array container is just 2.3K

A generic container implemented with pointers to void is equally
functional and less work for me. What are the reasons that could lead
me to adopting your approach?
Specifically:
* Even your PoC code is bloated and clearly erroneous (and dangerous)
in some places. Why would I use it over libraries that provably work
correctly, and have been for a while now (such as GLib)?
* It is my belief is that metaprogramming in C offers no real benefits
for its hassle, other than e-penis size. If you disagree, what is the
real incentive behind C metaprogramming? Is there something clearly
beneficial we can extract out of it, given that the language is, by
design, inadequate for that purpose?
* Memory is generally not an issue at this point. If one is severely
restricted, a custom container might be desirable - but such a
discussion with no practical area of application is moot. In extreme
cases one might not need it at all, because the gain from not having
the need for a pointer to void for each data element might be
significant, but if that gain is maximum then I'm better off using C
arrays and finding clever algorithms to manipulate the data..
* Can you show me an application which uses your scheme effectively
and demonstrably benefits over "void *" containers?

jacob navia

unread,
Apr 19, 2010, 10:22:58 AM4/19/10
to
Michael Foukarakis a écrit :

> On Apr 19, 10:17 am, jacob navia <ja...@spamsink.net> wrote:
>> Gene a crit :
>>
>>> Fine! Some notes:
>>> Generating code from templates like this is pretty standard in larger
>>> code bases. But I've generally seen a short script in a language like
>>> awk or perl used to transform the template instead of C. I think what
>>> you've done in C represents one line of Perl, for example.
>> I do not think so, if you look carefully at the code you will see that
>> it does more than what you believe. And in any case, I do not want to
>> force the users of the library to install another programming language
>> and all the associated hassle...
>
> Nobody relies on one programming language for everything. If one
> doesn't know sed/awk, (s)he's doomed anyway.
>
>

Again. Please give me an sed program that does what the expander does.
True, you *could* write it but it be quite awk...ward...


>>> The down side in a big system with either approach will be code
>>> bloat.
>> This is always the case for templates. You can, however, compile all
>> those expanded templates into a library, and the linker will pukll out
>> of that library only those files that are effectively used. The code
>> bloat of the template for the flexible array container is just 2.3K
>
> A generic container implemented with pointers to void is equally
> functional and less work for me.

If you read what I wrote you will notice that the library will be
provided with TWO versions: one with a generic void * approach, and
another in the form of templates that can be expanded with the given
utility.


> What are the reasons that could lead
> me to adopting your approach?
> Specifically:
> * Even your PoC code is bloated and clearly erroneous (and dangerous)
> in some places. Why would I use it over libraries that provably work
> correctly, and have been for a while now (such as GLib)?

The Glib is unusable since any allocation that fails exits the program.
Obviously you missed several discussions in this newsgroup about that.


> * It is my belief is that metaprogramming in C offers no real benefits
> for its hassle, other than e-penis size. If you disagree, what is the
> real incentive behind C metaprogramming? Is there something clearly
> beneficial we can extract out of it, given that the language is, by
> design, inadequate for that purpose?

If you start like this, granted your penis is bigger.

happy now?

> * Memory is generally not an issue at this point. If one is severely
> restricted, a custom container might be desirable - but such a
> discussion with no practical area of application is moot. In extreme
> cases one might not need it at all, because the gain from not having
> the need for a pointer to void for each data element might be
> significant, but if that gain is maximum then I'm better off using C
> arrays and finding clever algorithms to manipulate the data..
> * Can you show me an application which uses your scheme effectively
> and demonstrably benefits over "void *" containers?

You did not read my proposal. Read it againin the context of the
discussion. I propose to give users

(1) A generic library with void *.
(2) A template library using the template expander.

The user can choose between the two and both are binary compatible.

jacob navia

unread,
Apr 19, 2010, 10:38:34 AM4/19/10
to
Ben Bacarisse a écrit :
>
>
> missing #include <stdio.h>
>

Yes, bad cut/paste


> delta is not declared.

Yes, I eliminated that variable but forgot to erase all the
corresponding lines.

>
>> while (fgets(buf,sizeof(buf)-1,input)) {
>
> why -1? (Schildt does this in some of his fgets examples.)
>

well, this is a common bug then...


>
> Again, j is probably what you mean. As you have it, tmpBuf may not be a
> proper string and the assignment might even be off the end of the array.
>

True, that is a bug.

>> strrepl(tmpBuf,"$(TYPE)",TypeDefinition,outputFile);
>
> strrepl can't tell whether there is room -- that's why you do a "dry
> run" in the main code below. Surely you need to do that here also?
>

I assumed that 1024 would suffice but this is also a bug, that shouldn't
be assumed.


>> if (output != NULL)
>> fclose(output);
>> output = fopen(outputFile,"w");
>
> This is dangerous. If the loop above cut the filename short, this fopen
> could destroy an unintended file.
>


Yes, I could test if the file exists before erasing it.

>
> I think "$(TYPE)" deserves a #define. You use it four times.
>

True. I could do that.

>> fwrite(tmpLine,1,strlen(tmpLine),output);
>
> why not fputs?
>

because... I did not think about that.

>
> I don't like the fact that the returned result is different when output
> is or is not NULL. Your text describes one half of this behaviour, but
> not the other. I'd make it always return the number of characters
> needed or actually written.
>

The full doc is furnished with the lcc-win distribution.

>
> It also supposes that the type can be used in that same syntactic
> position as a plain old type like int. There are therefore other cases
> where a typedef is needed.
>

Interesting, can you tell me an example?

Thanks, and many thanks for your attentive reading. Will fix those
bugs.

jacob

bartc

unread,
Apr 19, 2010, 11:08:11 AM4/19/10
to
"jacob navia" <ja...@spamsink.net> wrote in message
news:hqhpt8$g4b$1...@speranza.aioe.org...
> Ben Bacarisse a écrit :


>> It also supposes that the type can be used in that same syntactic
>> position as a plain old type like int. There are therefore other cases
>> where a typedef is needed.
>>
>
> Interesting, can you tell me an example?

Anything involving *, [] or () perhaps?

--
Bartc

ImpalerCore

unread,
Apr 19, 2010, 11:47:28 AM4/19/10
to

Just a quick question. Do you allow an array list of pointers? Seems
like there may be an issue. If you had an array list of struct
my_data*, would the '*' mess up the syntax? i.e.

static int RemoveAt(struct my_data*_Array *AL,size_t idx)

Best regards,
John D.

> jacob

jacob navia

unread,
Apr 19, 2010, 11:53:10 AM4/19/10
to
ImpalerCore a écrit :

>
> Just a quick question. Do you allow an array list of pointers? Seems
> like there may be an issue. If you had an array list of struct
> my_data*, would the '*' mess up the syntax? i.e.
>
> static int RemoveAt(struct my_data*_Array *AL,size_t idx)


Yes, that would be a case too. Note that you NEED a typedef
"struct data" will have problems even without the "*".

Keith Thompson

unread,
Apr 19, 2010, 11:57:35 AM4/19/10
to
jacob navia <ja...@spamsink.net> writes:
> Ben Bacarisse a écrit :
[...]

> > It also supposes that the type can be used in that same syntactic
> > position as a plain old type like int. There are therefore other cases
> > where a typedef is needed.
> >
>
> Interesting, can you tell me an example?

int[10]

[...]

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Ben Bacarisse

unread,
Apr 19, 2010, 12:05:06 PM4/19/10
to
jacob navia <ja...@spamsink.net> writes:

> Ben Bacarisse a écrit :
[You've snipped my attributions. For the record, I did include
attribution lines.]

<snip>


>>> strrepl(tmpBuf,"$(TYPE)",TypeDefinition,outputFile);
>>
>> strrepl can't tell whether there is room -- that's why you do a "dry
>> run" in the main code below. Surely you need to do that here also?
>>
>
> I assumed that 1024 would suffice but this is also a bug, that
> shouldn't be assumed.

If you assume 1024 is enough, the test against that size in the loop
(now snipped) would have been pointless. You test for enough room in
once place and not in another.

>>> if (output != NULL)
>>> fclose(output);
>>> output = fopen(outputFile,"w");
>>
>> This is dangerous. If the loop above cut the filename short, this fopen
>> could destroy an unintended file.
>
> Yes, I could test if the file exists before erasing it.

That would make the tool hard to use. Every time it is re-run the
output files would have to be removed first. Even if you don't mind
that, the fopen could still create a file in a hard to guess location.

A better solution is to stop the program if the file name is truncated
in any way.

<snip>


>> It also supposes that the type can be used in that same syntactic
>> position as a plain old type like int. There are therefore other cases
>> where a typedef is needed.
>
> Interesting, can you tell me an example?

Function types and array types come to mind. It is legitimate to have a
collection type that holds pointers to either of these kinds of type,
but

expand eg.c "int[2]"

generates the wrong syntax. This is not a problem -- it is probably
better to use a typedef in this sort of situation anyway -- but the
restriction should be noted.


>
> Thanks, and many thanks for your attentive reading. Will fix those
> bugs.
>
> jacob

--
Ben.

Morris Keesan

unread,
Apr 19, 2010, 8:43:21 PM4/19/10
to
On Sat, 17 Apr 2010 04:31:29 -0400, jacob navia <ja...@spamsink.net> wrote:


> int strrepl(char *InputString,
> char *StringToFind,
> char *StringToReplace,
> char *output)

Maybe I'm missing something, but this appears to be using a name which
is reserved for future library extensions (C99 7.26.11). str_repl would
be a safer name. Also, this would benefit from some judicious use of
the "const" attribute, so that the reader of the code could tell at a
glance which of the argument strings are safe from modification. Based
on a quick skim of the code, I suspect that this could be

int str_repl(const char *InputString,
const char *StringToFind,
const char *StringToReplace,
char *output)

and it would be much nicer to the reader and the compiler to make this
explicit.

--
Morris Keesan -- mke...@post.harvard.edu

Nick

unread,
Apr 20, 2010, 2:40:28 AM4/20/10
to
"Morris Keesan" <mke...@post.harvard.edu> writes:

I confess to not having examined the original code, but if that function
does the obvious it looks like a buffer overflow waiting to happen.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk

Nick Keighley

unread,
Apr 20, 2010, 3:09:43 AM4/20/10
to
On 19 Apr, 14:41, Michael Foukarakis <electricde...@gmail.com> wrote:
> On Apr 19, 10:17 am, jacob navia <ja...@spamsink.net> wrote:
> > Gene a crit :

[...]

> > > Generating code from templates like this is pretty standard in larger
> > > code bases. But I've generally seen a short script in a language like
> > > awk or perl used to transform the template instead of C.  I think what
> > > you've done in C represents one line of Perl, for example.
>
> > I do not think so, if you look carefully at the code you will see that
> > it does more than what you believe. And in any case, I do not want to
> > force the users of the library to install another programming language
> > and all the associated hassle...
>
> Nobody relies on one programming language for everything. If one
> doesn't know sed/awk, (s)he's doomed anyway.

I never got the hang of sed and I find awk very limited (lack of
anchored patterns). I use perl for what i used to use awk for. It *is*
a bit of pain to have to download it and it is gigantic for what I
want. Serves me right for using Windows.


> > > The down side in a big system with either approach will be code
> > > bloat.
>
> > This is always the case for templates. You can, however, compile all
> > those expanded templates into a library, and the linker will pukll out
> > of that library only those files that are effectively used. The code
> > bloat of the template for the flexible array container is just 2.3K

impressive. On a desk top 2.3k is down in the noise.

> A generic container implemented with pointers to void is equally
> functional and less work for me. What are the reasons that could lead
> me to adopting your approach?

no one is compelling you to use it. The void* appraoch is less
typesafe. Usually pretty ugly too.

> Specifically:
>
> * Even your PoC code is bloated and clearly erroneous (and dangerous)
> in some places.

could we have some specific criticism. If his code is broken or unsafe
we'd like to know why.

> Why would I use it over libraries that provably work
> correctly, and have been for a while now (such as GLib)?

no one is twisting your arm


> * It is my belief is that metaprogramming in C offers no real benefits
> for its hassle,

"C Unleashed" (if I recall corrctly) uses a generic approach (though
less sophisticated tahn Jacob's)

> other than e-penis size.

idiot

> If you disagree, what is the
> real incentive behind C metaprogramming?

type safety. A quick an easy way to produce efficeint container code.

> [REPETITION] given that the language is, by


> design, inadequate for that purpose?

well if he's done it plainly isn't inadequate


> * Memory is generally not an issue at this point. If one is severely
> restricted, a custom container might be desirable

as opposed to what?

> - but such a
> discussion with no practical area of application is moot.

I disagree

> In extreme
> cases one might not need it at all, because the gain from not having
> the need for a pointer to void for each data element might be
> significant, but if that gain is maximum then I'm better off using C
> arrays and finding clever algorithms to manipulate the data..
>
> * Can you show me an application which uses your scheme effectively
> and demonstrably benefits over "void *" containers?

I think you've already made your mind up.


--

You are in a clearing. You can see a spire in the distance.
You can also see a copy of "C Unleashed".
: INV
You have;
a DeathStation 900 laptop,
a voucher for a free pizza,
and a torch.
: TAKE BOOK
You can't. It's too heavy.
Bill Godfrey (clc)

jacob navia

unread,
Apr 20, 2010, 4:03:23 AM4/20/10
to
Morris Keesan a écrit :

> On Sat, 17 Apr 2010 04:31:29 -0400, jacob navia <ja...@spamsink.net> wrote:
>
>
>> int strrepl(char *InputString,
>> char *StringToFind,
>> char *StringToReplace,
>> char *output)
>
> Maybe I'm missing something, but this appears to be using a name which
> is reserved for future library extensions (C99 7.26.11).

It is a library extension. It is part of the lcc-win standard library.
That's why the name.

str_repl would
> be a safer name. Also, this would benefit from some judicious use of
> the "const" attribute, so that the reader of the code could tell at a
> glance which of the argument strings are safe from modification. Based
> on a quick skim of the code, I suspect that this could be
>
> int str_repl(const char *InputString,
> const char *StringToFind,
> const char *StringToReplace,
> char *output)
>
> and it would be much nicer to the reader and the compiler to make this
> explicit.
>

True. That is an oversight. Thanks

jacob navia

unread,
Apr 20, 2010, 4:05:53 AM4/20/10
to
Nick a écrit :

> I confess to not having examined the original code, but if that function
> does the obvious it looks like a buffer overflow waiting to happen.

Since you know nothing but that prototype you do not know that a NULL
value for output makes strrepl calculate the length of the required
string if all the replacements would be done. That can be used to
allocate a new buffer or ensure that no buffer overflows happen. Then,
you call it with a correct buffer.

I explained that in the text and used it in the code.

jacob navia

unread,
Apr 20, 2010, 4:09:50 AM4/20/10
to
Nick Keighley a écrit :

>
> no one is compelling you to use it. The void* appraoch is less
> typesafe. Usually pretty ugly too.
>

The template approach allows you to optimize stuff, passing calculations
from the run time to the compile time. I think that is the main interest
of templates anyway.

>> Specifically:
>>
>> * Even your PoC code is bloated and clearly erroneous (and dangerous)
>> in some places.
>
> could we have some specific criticism. If his code is broken or unsafe
> we'd like to know why.
>
>> Why would I use it over libraries that provably work
>> correctly, and have been for a while now (such as GLib)?
>
> no one is twisting your arm
>

The Glib is unusable since any allocation failure provokes the exit of
the program. We have discussed that in this newsgroup several times.

Michael Foukarakis

unread,
Apr 20, 2010, 5:10:51 AM4/20/10
to
On Apr 19, 5:22 pm, jacob navia <ja...@jacob.remcomp.fr> wrote:
> Michael Foukarakis a écrit :
>
>
>
> > On Apr 19, 10:17 am, jacob navia <ja...@spamsink.net> wrote:
> >> Gene a crit :
>
> >>> Fine!  Some notes:
> >>> Generating code from templates like this is pretty standard in larger
> >>> code bases. But I've generally seen a short script in a language like
> >>> awk or perl used to transform the template instead of C.  I think what
> >>> you've done in C represents one line of Perl, for example.
> >> I do not think so, if you look carefully at the code you will see that
> >> it does more than what you believe. And in any case, I do not want to
> >> force the users of the library to install another programming language
> >> and all the associated hassle...
>
> > Nobody relies on one programming language for everything. If one
> > doesn't know sed/awk, (s)he's doomed anyway.
>
> Again. Please give me an sed program that does what the expander does.
> True, you *could* write it but it be quite awk...ward...

(to all who don't approve of sed/awk...) I used sed/awk as an example.
Please don't focus on all things irrelevant and let's have a
discussion, for once..


> >>> The down side in a big system with either approach will be code
> >>> bloat.
> >> This is always the case for templates. You can, however, compile all
> >> those expanded templates into a library, and the linker will pukll out
> >> of that library only those files that are effectively used. The code
> >> bloat of the template for the flexible array container is just 2.3K
>
> > A generic container implemented with pointers to void is equally
> > functional and less work for me.
>
> If you read what I wrote you will notice that the library will be
> provided with TWO versions: one with a generic void * approach, and
> another in the form of templates that can be expanded with the given
> utility.

Yes, and I pointed out that the second version seems an overkill for
me. Two completely different things. Like apples and oranges. Let's
move on, please.

> > What are the reasons that could lead
> > me to adopting your approach?
> > Specifically:
> > * Even your PoC code is bloated and clearly erroneous (and dangerous)
> > in some places. Why would I use it over libraries that provably work
> > correctly, and have been for a while now (such as GLib)?
>
> The Glib is unusable since any allocation that fails exits the program.
> Obviously you missed several discussions in this newsgroup about that.

There's always the option of not using GLib's allocators. GLib is very
much usable, but even if it's not, let's not digress - this is about
your implementation versus other working implementations.

> > * It is my belief is that metaprogramming in C offers no real benefits
> > for its hassle, other than e-penis size. If you disagree, what is the
> > real incentive behind C metaprogramming? Is there something clearly
> > beneficial we can extract out of it, given that the language is, by
> > design, inadequate for that purpose?
>
> If you start like this, granted your penis is bigger.
>
> happy now?

What? Why don't you try addressing my question. I'm trying to learn
something and you keep acting like a douche.

> > * Memory is generally not an issue at this point. If one is severely
> > restricted, a custom container might be desirable - but such a
> > discussion with no practical area of application is moot. In extreme
> > cases one might not need it at all, because the gain from not having
> > the need for a pointer to void for each data element might be
> > significant, but if that gain is maximum then I'm better off using C
> > arrays and finding clever algorithms to manipulate the data..
> > * Can you show me an application which uses your scheme effectively
> > and demonstrably benefits over "void *" containers?
>
> You did not read my proposal. Read it againin the context of the
> discussion. I propose to give users
>
> (1) A generic library with void *.
> (2) A template library using the template expander.
>
> The user can choose between the two and both are binary compatible.

Look, why don't you try abandoning that monolithic pov for a few
seconds, and understand what I'm asking: Given your (or anybody
else's) two versions of a container, what practical advantages does
your "template library" offer over the generic one?

I'm just trying to have an intelligent discussion here. If you're not
able or willing to do so in your next post, then don't even bother.

Michael Foukarakis

unread,
Apr 20, 2010, 5:31:01 AM4/20/10
to
On Apr 20, 10:09 am, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:

> On 19 Apr, 14:41, Michael Foukarakis <electricde...@gmail.com> wrote:
>
> > On Apr 19, 10:17 am, jacob navia <ja...@spamsink.net> wrote:
> > > Gene a crit :
>
> [...]
>
> > > > Generating code from templates like this is pretty standard in larger
> > > > code bases. But I've generally seen a short script in a language like
> > > > awk or perl used to transform the template instead of C.  I think what
> > > > you've done in C represents one line of Perl, for example.
>
> > > I do not think so, if you look carefully at the code you will see that
> > > it does more than what you believe. And in any case, I do not want to
> > > force the users of the library to install another programming language
> > > and all the associated hassle...
>
> > Nobody relies on one programming language for everything. If one
> > doesn't know sed/awk, (s)he's doomed anyway.
>
> I never got the hang of sed and I find awk very limited (lack of
> anchored patterns). I use perl for what i used to use awk for. It *is*
> a bit of pain to have to download it and it is gigantic for what I
> want.  Serves me right for using Windows.

Again: replace sed/awk with anything else. My example is not
important, the principle is.

> > > > The down side in a big system with either approach will be code
> > > > bloat.
>
> > > This is always the case for templates. You can, however, compile all
> > > those expanded templates into a library, and the linker will pukll out
> > > of that library only those files that are effectively used. The code
> > > bloat of the template for the flexible array container is just 2.3K
>
> impressive. On a desk top 2.3k is down in the noise.
>
> > A generic container implemented with pointers to void is equally
> > functional and less work for me. What are the reasons that could lead
> > me to adopting your approach?
>
> no one is compelling you to use it. The void* appraoch is less
> typesafe. Usually pretty ugly too.
>
> > Specifically:
>
> > * Even your PoC code is bloated and clearly erroneous (and dangerous)
> > in some places.
>
> could we have some specific criticism. If his code is broken or unsafe
> we'd like to know why.

Ben Bacarisse pointed out quite a few errors. I think they're enough
to illustrate the point.

> > Why would I use it over libraries that provably work
> > correctly, and have been for a while now (such as GLib)?
>
> no one is twisting your arm

What the hell. Why are you getting so wound up? I'm asking a direct
question and your only response is an asinine comment? Let me clarify
my intentions to your amusing little mind:

I'm asking because I'm INTERESTED.

>
> > * It is my belief is that metaprogramming in C offers no real benefits
> > for its hassle,
>
> "C Unleashed" (if I recall corrctly) uses a generic approach (though
> less sophisticated tahn Jacob's)
>
> > other than e-penis size.
>
> idiot
> > If you disagree, what is the
> > real incentive behind C metaprogramming?
>
> type safety. A quick an easy way to produce efficeint container code.

Finally, a real answer. Comment below.

> > given that the language is, by
> > design, inadequate for that purpose?
>
> well if he's done it plainly isn't inadequate

C is not fully capable of introspection. This is a fact. It is the
reason behind the following:
- the extra preprocessing step(s) in producing the "template library".
- the inability to deal with some cases (see above posts) or avoiding
significant storage costs for such types.

, hence the inadequacy. My question still stands - what is the real
benefit offered here, because it's not usability, user friendliness,
or "being generic", all of which are crucial in development and usage
of containers and libraries in general.

> > * Memory is generally not an issue at this point. If one is severely
> > restricted, a custom container might be desirable
>
> as opposed to what?

I'm not interested in the obvious.

> > - but such a
> > discussion with no practical area of application is moot.
>
> I disagree

Why? Is there a point to libraries that are being implemented without
the intention of ever being used?

> > In extreme
> > cases one might not need it at all, because the gain from not having
> > the need for a pointer to void for each data element might be
> > significant, but if that gain is maximum then I'm better off using C
> > arrays and finding clever algorithms to manipulate the data..
>
> > * Can you show me an application which uses your scheme effectively
> > and demonstrably benefits over "void *" containers?
>
> I think you've already made your mind up.

No, I haven't, that's why I'm asking questions. If you won't help me,
why don't you just go find your lost manhood elsewhere.

Ian Collins

unread,
Apr 20, 2010, 6:12:01 AM4/20/10
to
On 04/20/10 09:10 PM, Michael Foukarakis wrote:

> Look, why don't you try abandoning that monolithic pov for a few
> seconds, and understand what I'm asking: Given your (or anybody
> else's) two versions of a container, what practical advantages does
> your "template library" offer over the generic one?

The classic answer is type safety and efficiency.

An example often cited is the difference between qsort and a template
base sort. There isn't anything the compiler can do to optimise sorting
for a particular type with a "generic" function like qsort. On the
other hand, with a template the compiler knows the types being sorted
and can optimise accordingly.

Even a trivial operation such as searching will be much more efficient
for a template based container. Not having to use function pointers may
lead to a reduction in code size for the template based version. It
certainly would for sorting or searching an array of int for example.

A "generic" container will normally use void* for elements, which is
fine for containers of pointers to objects, but truly horrible for
containers of objects (a sorted list of int for example). In the case
of containers of pointers to objects, the template approach can add a
zero cost, type safe wrapper round the "generic" container. The wrapper
handles the casting to and from void* and the wrapper functions, being
trivial, will be optimised away.

--
Ian Collins

Michael Foukarakis

unread,
Apr 20, 2010, 6:53:53 AM4/20/10
to
On Apr 20, 1:12 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> On 04/20/10 09:10 PM, Michael Foukarakis wrote:
>
> > Look, why don't you try abandoning that monolithic pov for a few
> > seconds, and understand what I'm asking: Given your (or anybody
> > else's) two versions of a container, what practical advantages does
> > your "template library" offer over the generic one?
>
> The classic answer is type safety and efficiency.
>
> An example often cited is the difference between qsort and a template
> base sort.  There isn't anything the compiler can do to optimise sorting
> for a particular type with a "generic" function like qsort.  On the
> other hand, with a template the compiler knows the types being sorted
> and can optimise accordingly.
>
> Even a trivial operation such as searching will be much more efficient
> for a template based container.  Not having to use function pointers may
> lead to a reduction in code size for the template based version.  It
> certainly would for sorting or searching an array of int for example.

I agree, although I can only guess the extent in which those
optimizations will save space/time.

> A "generic" container will normally use void* for elements, which is
> fine for containers of pointers to objects, but truly horrible for
> containers of objects (a sorted list of int for example).  In the case
> of containers of pointers to objects, the template approach can add a
> zero cost, type safe wrapper round the "generic" container.  The wrapper
> handles the casting to and from void* and the wrapper functions, being
> trivial, will be optimised away.

While you are right, I'm still questioning the usefulness of a list
([vector|tree|...]) of basic types. It just feels like it's too much
space and effort for something that could be done with a int[]. But I
guess that's all academic, and the answer depends heavily on intent
and application.

Ian Collins

unread,
Apr 20, 2010, 7:49:47 AM4/20/10
to

Over in C++ land, they are very common. Everywhere one would use a
dynamic array of something in C, in C++ a vector tends to be used
abstract away the memory management.

--
Ian Collins

jacob navia

unread,
Apr 20, 2010, 8:45:02 AM4/20/10
to
Ian Collins a écrit :

> On 04/20/10 09:10 PM, Michael Foukarakis wrote:
>
>> Look, why don't you try abandoning that monolithic pov for a few
>> seconds, and understand what I'm asking: Given your (or anybody
>> else's) two versions of a container, what practical advantages does
>> your "template library" offer over the generic one?
>
> The classic answer is type safety and efficiency.
>

Exactly.

> An example often cited is the difference between qsort and a template
> base sort. There isn't anything the compiler can do to optimise sorting
> for a particular type with a "generic" function like qsort. On the
> other hand, with a template the compiler knows the types being sorted
> and can optimise accordingly.
>
> Even a trivial operation such as searching will be much more efficient
> for a template based container. Not having to use function pointers may
> lead to a reduction in code size for the template based version. It
> certainly would for sorting or searching an array of int for example.
>
> A "generic" container will normally use void* for elements, which is
> fine for containers of pointers to objects, but truly horrible for
> containers of objects (a sorted list of int for example). In the case
> of containers of pointers to objects, the template approach can add a
> zero cost, type safe wrapper round the "generic" container. The wrapper
> handles the casting to and from void* and the wrapper functions, being
> trivial, will be optimised away.

Another point is that in my implementation (I do not know if in C++ that holds)
you can customize the generated code. For instance it doesn't make sense to
have a pointer to objects that are smaller than a pointer size. It would be
much better to store directly the object in the place of the pointer and
access it directly.

jacob navia

unread,
Apr 20, 2010, 8:46:34 AM4/20/10
to
Ian Collins a écrit :

The same holds here. True, you can program a flexible array in C (the proof is that I did it!) but
many people will not do that because of the effort involved. If there is a ready-made library to do
that for you it becomes much easier to do one.

bartc

unread,
Apr 20, 2010, 9:20:34 AM4/20/10
to
"jacob navia" <ja...@jacob.remcomp.fr> wrote in message
news:4bcd5fcb$0$28938$ba4a...@reader.news.orange.fr...
> Morris Keesan a �crit :

>> be a safer name. Also, this would benefit from some judicious use of
>> the "const" attribute, so that the reader of the code could tell at a
>> glance which of the argument strings are safe from modification. Based
>> on a quick skim of the code, I suspect that this could be
>>
>> int str_repl(const char *InputString,
>> const char *StringToFind,
>> const char *StringToReplace,
>> char *output)
>>
>> and it would be much nicer to the reader and the compiler to make this
>> explicit.
>>
>
> True. That is an oversight. Thanks

'const's are just extra clutter (imo). What is odd though is having an input
string called InputString, and an output string called just output, rather
than OutputString.

--
Bartc

Nick Keighley

unread,
Apr 20, 2010, 9:31:54 AM4/20/10
to
On 20 Apr, 10:10, Michael Foukarakis <electricde...@gmail.com> wrote:
> On Apr 19, 5:22 pm, jacob navia <ja...@jacob.remcomp.fr> wrote:

> > > * It is my belief is that metaprogramming in C offers no real benefits
> > > for its hassle, other than e-penis size.

[...]

> > If you start like this, granted your penis is bigger.
>
> > happy now?
>
> What? Why don't you try addressing my question. I'm trying to learn
> something and you keep acting like a douche.

well you satrted on the penis size stuff. Why'd you do that if you
wanted an intelligent discussion?

Nick Keighley

unread,
Apr 20, 2010, 10:01:33 AM4/20/10
to

this is a very good point. In C++ I pick vector for most data
structures. And automatically get a flexible array. Implementing the
same thing in C isn't particularly difficult but isn't usually worth
the trouble.


Andrew Poelstra

unread,
Apr 20, 2010, 10:04:21 AM4/20/10
to
On 2010-04-20, bartc <ba...@freeuk.com> wrote:
>
> 'const's are just extra clutter (imo). What is odd though is having an input
> string called InputString, and an output string called just output, rather
> than OutputString.
>

const assures the user he can pass string literals.

const assures the programmer that, if he does something Bad and
modifies a supposedly-input string, the compiler will catch him.

const makes the interface more concise and descriptive.


--
Andrew Poelstra
http://www.wpsoftware.net/andrew

lawrenc...@siemens.com

unread,
Apr 20, 2010, 9:51:59 AM4/20/10
to
Ian Collins <ian-...@hotmail.com> wrote:
>
> An example often cited is the difference between qsort and a template
> base sort. There isn't anything the compiler can do to optimise sorting
> for a particular type with a "generic" function like qsort.

It can, with a little effort, implement qsort as an inline function,
which then allows at least as much optimization as templates do.
--
Larry Jones

I hope Mom and Dad didn't rent out my room. -- Calvin

Nick Keighley

unread,
Apr 20, 2010, 10:19:48 AM4/20/10
to
On 20 Apr, 10:31, Michael Foukarakis <electricde...@gmail.com> wrote:
> On Apr 20, 10:09 am, Nick Keighley <nick_keighley_nos...@hotmail.com>
> > On 19 Apr, 14:41, Michael Foukarakis <electricde...@gmail.com> wrote:
> > > On Apr 19, 10:17 am, jacob navia <ja...@spamsink.net> wrote:
> > > > Gene a crit :

> > > > > Generating code from templates like this is pretty standard in larger
> > > > > code bases. But I've generally seen a short script in a language like
> > > > > awk or perl used to transform the template instead of C.  I think what
> > > > > you've done in C represents one line of Perl, for example.
>
> > > > I do not think so, if you look carefully at the code you will see that
> > > > it does more than what you believe. And in any case, I do not want to
> > > > force the users of the library to install another programming language
> > > > and all the associated hassle...
>
> > > Nobody relies on one programming language for everything. If one
> > > doesn't know sed/awk, (s)he's doomed anyway.
>
> > I never got the hang of sed and I find awk very limited (lack of
> > anchored patterns). I use perl for what i used to use awk for. It *is*
> > a bit of pain to have to download it and it is gigantic for what I
> > want.  Serves me right for using Windows.
>
> Again: replace sed/awk with anything else. My example is not
> important, the principle is.


perhaps its the way you phrase things. I know of plenty of programmers
that don't use these sorts of tools. I'd never thought of them as
"doomed". Limited perhaps.

<snip>

> > > Specifically:
>
> > > * Even your PoC code is bloated and clearly erroneous (and dangerous)
> > > in some places.
>
> > could we have some specific criticism. If his code is broken or unsafe
> > we'd like to know why.
>
> Ben Bacarisse pointed out quite a few errors. I think they're enough
> to illustrate the point.

I hadn't read that post at the time. I note Jacob responded positivly
pretyty much all of it (actually probably all of it). His early
implementation has bugs they are being fixed.


> > > Why would I use it over libraries that provably work
> > > correctly, and have been for a while now (such as GLib)?
>
> > no one is twisting your arm
>
> What the hell. Why are you getting so wound up? I'm asking a direct
> question and your only response is an asinine comment? Let me clarify
> my intentions to your amusing little mind:
>
> I'm asking because I'm INTERESTED.

you don't give that impression. It seems more like "I don't think this
is a good idea in C and I can't see any reason for it". This is even
after a couple of people have pointed out the possible benefit.

<snip>

> > > other than e-penis size.
>
> > idiot


[...]

> > > If you disagree, what is the
> > > real incentive behind C metaprogramming?
>

> > type safety. A quick and easy way to produce efficient container code.


>
> Finally, a real answer. Comment below.

[...]

> > > given that the language is, by
> > > design, inadequate for that purpose?
>
> > well if he's done it plainly isn't inadequate
>
> C is not fully capable of introspection. This is a fact. It is the
> reason behind the following:
> - the extra preprocessing step(s) in producing the "template library".

C++ jumps through rather similar hoops under the hood


> - the inability to deal with some cases (see above posts) or avoiding
> significant storage costs for such types.
>
> , hence the inadequacy. My question still stands - what is the real
> benefit offered here, because it's not usability, user friendliness,
> or "being generic",

again you just say that


> all of which are crucial in development and usage
> of containers and libraries in general.

<snip>

> > > - but such a
> > > discussion with no practical area of application is moot.
>
> > I disagree
>
> Why? Is there a point to libraries that are being implemented without
> the intention of ever being used?

I don't see those things as saying the same thing. I thought you were
asking for a particular application. Containers don't work that way.
What application *wouldn't* it work on.

> > > In extreme
> > > cases one might not need it at all, because the gain from not having
> > > the need for a pointer to void for each data element might be
> > > significant, but if that gain is maximum then I'm better off using C
> > > arrays and finding clever algorithms to manipulate the data..
>
> > > * Can you show me an application which uses your scheme effectively
> > > and demonstrably benefits over "void *" containers?

find a C++ that uses an STL container and explain why the same sort of
thing couldn't be used with a generic container in C


> > I think you've already made your mind up.
>
> No, I haven't, that's why I'm asking questions. If you won't help me,
> why don't you just go find your lost manhood elsewhere.

ok you've memorised the puffin book of freud...

I think we're probably done here

Keith Thompson

unread,
Apr 20, 2010, 11:22:23 AM4/20/10
to
Michael Foukarakis <electr...@gmail.com> writes:
[...]

> No, I haven't, that's why I'm asking questions. If you won't help me,
> why don't you just go find your lost manhood elsewhere.

If you were really interested in having a serious discussion, you
probably wouldn't make silly remarks like that. If you're more
interested in annoying people, that's a great way to do it.

Keith Thompson

unread,
Apr 20, 2010, 11:23:55 AM4/20/10
to
Andrew Poelstra <apoe...@localhost.localdomain> writes:
> On 2010-04-20, bartc <ba...@freeuk.com> wrote:
> >
> > 'const's are just extra clutter (imo). What is odd though is
> > having an input string called InputString, and an output string
> > called just output, rather than OutputString.
> >
>
> const assures the user he can pass string literals.

Alas, string literals aren't const.

But it does make it possible to pass an argument of type const char*.

> const assures the programmer that, if he does something Bad and
> modifies a supposedly-input string, the compiler will catch him.
>
> const makes the interface more concise and descriptive.

Agreed.

Andrew Poelstra

unread,
Apr 20, 2010, 12:31:34 PM4/20/10
to
On 2010-04-20, Keith Thompson <ks...@mib.org> wrote:
> Andrew Poelstra <apoe...@localhost.localdomain> writes:
>> On 2010-04-20, bartc <ba...@freeuk.com> wrote:
>> >
>> > 'const's are just extra clutter (imo). What is odd though is
>> > having an input string called InputString, and an output string
>> > called just output, rather than OutputString.
>> >
>>
>> const assures the user he can pass string literals.
>
> Alas, string literals aren't const.
>

I meant, the user /knows/ he can /safely/ pass string literals.
Sadly, you are correct that the compiler doesn't care either way.

Kenny McCormack

unread,
Apr 20, 2010, 3:43:14 PM4/20/10
to
In article <lnmxwyc...@nuthaus.mib.org>,

Keith Thompson <ks...@mib.org> wrote:
>Michael Foukarakis <electr...@gmail.com> writes:
>[...]
>> No, I haven't, that's why I'm asking questions. If you won't help me,
>> why don't you just go find your lost manhood elsewhere.
>
>If you were really interested in having a serious discussion, you
>probably wouldn't make silly remarks like that. If you're more
>interested in annoying people, that's a great way to do it.

God almighty, you (Kiki) are one piece of work!

--

> No, I haven't, that's why I'm asking questions. If you won't help me,
> why don't you just go find your lost manhood elsewhere.

CLC in a nutshell.

Nick

unread,
Apr 20, 2010, 3:21:45 PM4/20/10
to
jacob navia <ja...@nospam.org> writes:

> Nick a écrit :


>> jacob navia <ja...@jacob.remcomp.fr> writes:
>>
>>> Nick a écrit :
>>>
>>>> I confess to not having examined the original code, but if that function
>>>> does the obvious it looks like a buffer overflow waiting to happen.
>>> Since you know nothing but that prototype
>>

>> The way a lot of people program, of course!
>>
>
> You should read the documentation/manual page of a function you do not know.
> Yes, it can be used unsafely.


>
>>> you do not know that a NULL
>>> value for output makes strrepl calculate the length of the required
>>> string if all the replacements would be done. That can be used to
>>> allocate a new buffer or ensure that no buffer overflows happen. Then,
>>> you call it with a correct buffer.
>>>
>>> I explained that in the text and used it in the code.
>>

>> That means it /can/ be used safely, not that it will. I still feel that
>> a prototype like that is inviting the user to use it unsafely.
>>
>
> This is a difference of viewpoint here. You are used to C++ hand holding and need
> a complex machinery to guarantee you that no errors can happen.

No I'm not. I've never written C++ in my life. Not even to the extent
of tweaking a couple of lines in a pre-existing program (the way I could
say I've written PL/I or Perl for example).

I am used to people using functions that write unknown length strings
into string pointers, and what happens when they do.

>> You really want this function to take "strings", not "C strings". The
>> problem is that if you do this you end up re-inventing C++ (and while
>> there's almost certainly an argument for doing it better, I doubt
>> there's a market for it).
>>
>
> lcc-win provides counted strings using operator overloading. I have
> proposed that change to the language many times.

As I've suggested, the problem with strings with length is that there
are at least two ways of doing them - each of which has major advantages
and disadvantages. You don't need operator overloading to do it, of
course - that's another tack entirely.

It seems to me that you need to use your simpler enhancements (library,
not language syntax) to build the later features on - so use your
strings here rather than C-strings.

>> This is, I think, why no major list, string, hash or whatever library
>> has really taken over - unless you have the whole lot all integrated you
>> end up with so many limitations that you don't get most of the benefits.
>>
>
> I do not think so.

So which major list, string, hash or whatever library has really taken
over then? Or do you mean that after 20+ years you're going to succeed
where everyone else has failed (do you have any idea how many such
libraries are available)?

>> I think it's a bold thing you're doing, but ultimately I can't see it
>> taking off - it falls too much between C and C++.
>
> Yes, I know your position. I will fail, the library *will fail, etc.
> I disagree.

I didn't say "you would fail". I said "I don't see it taking off". Why
do you always turn any comments into some sort of personal attack on
yourself? It's very unbecoming. Nevertheless, wouldn't you be
expecting some sort of widespread take-up by now if it was to be the
success that every previous attempt has not been?

jacob navia

unread,
Apr 20, 2010, 2:47:48 PM4/20/10
to
Nick a écrit :
> jacob navia <ja...@jacob.remcomp.fr> writes:
>
>> Nick a écrit :
>>
>>> I confess to not having examined the original code, but if that function
>>> does the obvious it looks like a buffer overflow waiting to happen.
>> Since you know nothing but that prototype
>
> The way a lot of people program, of course!
>

You should read the documentation/manual page of a function you do not know.
Yes, it can be used unsafely.

>> you do not know that a NULL


>> value for output makes strrepl calculate the length of the required
>> string if all the replacements would be done. That can be used to
>> allocate a new buffer or ensure that no buffer overflows happen. Then,
>> you call it with a correct buffer.
>>
>> I explained that in the text and used it in the code.
>

> That means it /can/ be used safely, not that it will. I still feel that
> a prototype like that is inviting the user to use it unsafely.
>

This is a difference of viewpoint here. You are used to C++ hand holding and need
a complex machinery to guarantee you that no errors can happen.

C has a different philosophy, that leads to simpler code that can be as sure as
C++ code.

> There's not much you can do about it, I grant. And that's one of the
> problems I see with what you're trying to do with C - it doesn't have
> the infrastructure to support it.
>

To support what? String replacement?

Yes it has.

To support hand holding?

No it doesn't.


> You really want this function to take "strings", not "C strings". The
> problem is that if you do this you end up re-inventing C++ (and while
> there's almost certainly an argument for doing it better, I doubt
> there's a market for it).
>

lcc-win provides counted strings using operator overloading. I have
proposed that change to the language many times.

> This is, I think, why no major list, string, hash or whatever library
> has really taken over - unless you have the whole lot all integrated you
> end up with so many limitations that you don't get most of the benefits.
>

I do not think so.

> I think it's a bold thing you're doing, but ultimately I can't see it
> taking off - it falls too much between C and C++.

Yes, I know your position. I will fail, the library *will fail, etc.
I disagree.

jacob

lawrenc...@siemens.com

unread,
Apr 20, 2010, 12:38:51 PM4/20/10
to
Keith Thompson <ks...@mib.org> wrote:
> Andrew Poelstra <apoe...@localhost.localdomain> writes:
> >
> > const assures the user he can pass string literals.
>
> Alas, string literals aren't const.

But they're also not modifiable, so const *does* provide assurance. It
doesn't provide license, just assurance.
--
Larry Jones

Geez, I gotta have a REASON for everything? -- Calvin

Nick

unread,
Apr 20, 2010, 1:58:51 PM4/20/10
to
jacob navia <ja...@jacob.remcomp.fr> writes:

> Nick a écrit :
>
>> I confess to not having examined the original code, but if that function
>> does the obvious it looks like a buffer overflow waiting to happen.
>
> Since you know nothing but that prototype

The way a lot of people program, of course!

> you do not know that a NULL


> value for output makes strrepl calculate the length of the required
> string if all the replacements would be done. That can be used to
> allocate a new buffer or ensure that no buffer overflows happen. Then,
> you call it with a correct buffer.
>
> I explained that in the text and used it in the code.

That means it /can/ be used safely, not that it will. I still feel that


a prototype like that is inviting the user to use it unsafely.

There's not much you can do about it, I grant. And that's one of the


problems I see with what you're trying to do with C - it doesn't have
the infrastructure to support it.

You really want this function to take "strings", not "C strings". The


problem is that if you do this you end up re-inventing C++ (and while
there's almost certainly an argument for doing it better, I doubt
there's a market for it).

This is, I think, why no major list, string, hash or whatever library


has really taken over - unless you have the whole lot all integrated you
end up with so many limitations that you don't get most of the benefits.

I think it's a bold thing you're doing, but ultimately I can't see it


taking off - it falls too much between C and C++.

Ian Collins

unread,
Apr 20, 2010, 5:08:08 PM4/20/10
to
On 04/21/10 01:51 AM, lawrenc...@siemens.com wrote:
> Ian Collins<ian-...@hotmail.com> wrote:
>>
>> An example often cited is the difference between qsort and a template
>> base sort. There isn't anything the compiler can do to optimise sorting
>> for a particular type with a "generic" function like qsort.
>
> It can, with a little effort, implement qsort as an inline function,
> which then allows at least as much optimization as templates do.

Do you know of any that do?

--
Ian Collins

Ian Collins

unread,
Apr 20, 2010, 5:14:23 PM4/20/10
to
On 04/21/10 12:45 AM, jacob navia wrote:
> Ian Collins a écrit :
>>
>> A "generic" container will normally use void* for elements, which is
>> fine for containers of pointers to objects, but truly horrible for
>> containers of objects (a sorted list of int for example). In the case
>> of containers of pointers to objects, the template approach can add a
>> zero cost, type safe wrapper round the "generic" container. The
>> wrapper handles the casting to and from void* and the wrapper
>> functions, being trivial, will be optimised away.
>
> Another point is that in my implementation (I do not know if in C++ that
> holds)
> you can customize the generated code. For instance it doesn't make sense to
> have a pointer to objects that are smaller than a pointer size. It would be
> much better to store directly the object in the place of the pointer and
> access it directly.

I think that's what I said above!

--
Ian Collins

Richard Heathfield

unread,
Apr 20, 2010, 9:56:50 PM4/20/10
to
Nick wrote:
<snip>

> I am used to people using functions that write unknown length strings
> into string pointers, and what happens when they do.

I am not an lcc-win32 user so my reply is based purely on what I've read
in this thread. It seems that JN has provided a mechanism for
establishing the required length of the buffer, so that you can call it
once to get the buffer length (a step that you can skip if you already
know that length), and then call it to do the actual work. That seems to
me to be a perfectly reasonable interface. In that regard, JN's strrepl
is no less safe than strcpy. (In other regards, I wouldn't know; like I
said, I'm not an lcc-win32 user.)

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

Michael Foukarakis

unread,
Apr 21, 2010, 2:32:12 AM4/21/10
to
On Apr 20, 5:19 pm, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:

> > > > Why would I use it over libraries that provably work
> > > > correctly, and have been for a while now (such as GLib)?
>
> > > no one is twisting your arm
>
> > What the hell. Why are you getting so wound up? I'm asking a direct
> > question and your only response is an asinine comment? Let me clarify
> > my intentions to your amusing little mind:
>
> > I'm asking because I'm INTERESTED.
>
> you don't give that impression. It seems more like "I don't think this
> is a good idea in C and I can't see any reason for it". This is even
> after a couple of people have pointed out the possible benefit.

I keep re-reading my first post in the thread, it still seems like "I
don't think this is a good idea in C, can you give me some reasons for
it?". I'm sorry if you feel I should be addressing people and issues
in a certain way different than the one I'm currently doing so.

> <snip>
>
> > > > other than e-penis size.
>
> > > idiot
>
> [...]
>
> > > > If you disagree, what is the
> > > > real incentive behind C metaprogramming?
>
> > > type safety. A quick and easy way to produce efficient container code.
>
> > Finally, a real answer. Comment below.
>
> [...]
>
> > > > given that the language is, by
> > > > design, inadequate for that purpose?
>
> > > well if he's done it plainly isn't inadequate
>
> > C is not fully capable of introspection. This is a fact. It is the
> > reason behind the following:
> > - the extra preprocessing step(s) in producing the "template library".
>
> C++ jumps through rather similar hoops under the hood

You are correct. C++ is equally inadequate (for JN's approach, that
is).

> > - the inability to deal with some cases (see above posts) or avoiding
> > significant storage costs for such types.
>
> > , hence the inadequacy. My question still stands - what is the real
> > benefit offered here, because it's not usability, user friendliness,
> > or "being generic",
>
> again you just say that

OK, let's revisit each point:
- Is the library generic? Not if you have to preprocess it for each
different data type you want to store. The void * approach/
implementation, on the other hand, is.
- Is the library user friendly? Not if it introduces an extraneous
step in the building process, which gives more room for errors and
aggravates developers.
- Is the library usable? Yes, if one ignores the above two points.

> > all of which are crucial in development and usage
> > of containers and libraries in general.
>
> <snip>
>
> > > > - but such a
> > > > discussion with no practical area of application is moot.
>
> > > I disagree
>
> > Why? Is there a point to libraries that are being implemented without
> > the intention of ever being used?
>
> I don't see those things as saying the same thing. I thought you were
> asking for a particular application. Containers don't work that way.
> What application *wouldn't* it work on.

You misunderstood, again. The choice (or not) of a custom container
like JNs in a purely academic discussion (such as this, so far) is
irrelevant; the real question is what constraints does it operate
under, what problems it solves (besides storing things in a black
box), what benefits does it have over other container libraries. Do
you still disagree?

> > > > In extreme
> > > > cases one might not need it at all, because the gain from not having
> > > > the need for a pointer to void for each data element might be
> > > > significant, but if that gain is maximum then I'm better off using C
> > > > arrays and finding clever algorithms to manipulate the data..
>
> > > > * Can you show me an application which uses your scheme effectively
> > > > and demonstrably benefits over "void *" containers?
>
> find a C++ that uses an STL container and explain why the same sort of
> thing couldn't be used with a generic container in C

I didn't realize this was about turning C into C++. Do continue.

> > > I think you've already made your mind up.
>
> > No, I haven't, that's why I'm asking questions. If you won't help me,
> > why don't you just go find your lost manhood elsewhere.
>
> ok you've memorised the puffin book of freud...

I am guessing that was meant as an insult, can I choose to ignore you?

> I think we're probably done here

Indeed we are.

Nick Keighley

unread,
Apr 21, 2010, 3:22:57 AM4/21/10
to
I perhaps misunderstood your tone but early comment on penis size
doesn't seem like a good way to kick off a purely technical exchange.
Perhaps this is some sort of cultural difference (I've no idea of your
national or cultural background so don't take this as an attack on
either). Where I come from this sort of remark is rude. If I was
having a problem getting through to someone or they were being
particularly arrogant I might say something like that. But I'd pretty
well expect meaningful technical discussion to be over by then.


On 21 Apr, 07:32, Michael Foukarakis <electricde...@gmail.com> wrote:
> On Apr 20, 5:19 pm, Nick Keighley <nick_keighley_nos...@hotmail.com>

<snip>

> > > > > other than e-penis size.
>
> > > > idiot

> > > > > [...] what is the real incentive behind C metaprogramming?


>
> > > > type safety. A quick and easy way to produce efficient container code.

<snip>

> > > > > given that the language is, by design, inadequate for that purpose?
>
> > > > well if he's done it plainly isn't inadequate
>
> > > C is not fully capable of introspection. This is a fact. It is the
> > > reason behind the following:
>
> > > - the extra preprocessing step(s) in producing the "template library".
>
> > C++ jumps through rather similar hoops under the hood
>
> You are correct. C++ is equally inadequate (for JN's approach, that
> is).

why i C++ inadegate for egneric programming (I'm not trying to be
argumentative, I'm curious). The template syntax is pretty horrid but
it seems to work ok for basic containers.


> > > - the inability to deal with some cases (see above posts) or avoiding
> > > significant storage costs for such types.
>
> > > , hence the inadequacy. My question still stands - what is the real
> > > benefit offered here, because it's not usability, user friendliness,
> > > or "being generic",
>
> > again you just say that
>
> OK, let's revisit each point:
> - Is the library generic? Not if you have to preprocess it for each
> different data type you want to store. The void * approach/
> implementation, on the other hand, is.

well we're both expressing opinions here. But I don't see the
preprocessing step as particularly onerous (and C++ does it as well)
and with void* you've lost type safety (and possibly efficiency). If
you rate the simplicity of void* over type safety then I doubt someone
who is willing to suffer the code generation step in exchange for the
tyep saety is goign to chage your mind. This is why I thought your
mind was already made up (not necessarily a bad thing).

> - Is the library user friendly? Not if it introduces an extraneous
> step in the building process, which gives more room for errors and
> aggravates developers.

ibid

> - Is the library usable? Yes, if one ignores the above two points.

ibid

> > > all of which are crucial in development and usage
> > > of containers and libraries in general.
>

> > > > > - but such a
> > > > > discussion with no practical area of application is moot.
>
> > > > I disagree
>
> > > Why? Is there a point to libraries that are being implemented without
> > > the intention of ever being used?
>
> > I don't see those things as saying the same thing. I thought you were
> > asking for a particular application. Containers don't work that way.
> > What application *wouldn't* it work on.
>
> You misunderstood, again. The choice (or not) of a custom container
> like JNs in a purely academic discussion (such as this, so far) is
> irrelevant; the real question is what constraints does it operate
> under, what problems it solves (besides storing things in a black
> box), what benefits does it have over other container libraries. Do
> you still disagree?

no. But I can't see an application that needs a container that
couldn't work with Jacob's containers. I wrote a nodddy graphical
editor (in C++) it had a container of graphical objects. Which I think
was a std::vector of pointers to graphical objects. One of Jacob's
containers would do the job if I wanted to rewrite it in C.

I disagree with his desing decision to have a "generic" container
interface that might be an array, a linked list or a tree etc. But
that's another issue.

> > > > > In extreme
> > > > > cases one might not need it at all, because the gain from not having
> > > > > the need for a pointer to void for each data element might be
> > > > > significant, but if that gain is maximum then I'm better off using C
> > > > > arrays and finding clever algorithms to manipulate the data..
>
> > > > > * Can you show me an application which uses your scheme effectively
> > > > > and demonstrably benefits over "void *" containers?
>
> > find a C++ that uses an STL container and explain why the same sort of
> > thing couldn't be used with a generic container in C
>
> I didn't realize this was about turning C into C++. Do continue.

well there aren't going to be many examples from C as it doesn't have
standard containers...

You don't think the code gen overhead is worth the tyep safety and
possible efficiency. Ok.


> > > > I think you've already made your mind up.
>
> > > No, I haven't, that's why I'm asking questions. If you won't help me,
> > > why don't you just go find your lost manhood elsewhere.
>
> > ok you've memorised the puffin book of freud...
>
> I am guessing that was meant as an insult, can I choose to ignore you?

Puffin books were published by the Penguin publishing company and were
specifically aimed at children. Amateur Freudian analysis like this I
fell deserves such a comment. I'm amazed! You mean you weren't trying
to be rude to me? What? you were trying to help me over psycho-sexual
hangups? Why thank you! [saracasm]


> > I think we're probably done here
>
> Indeed we are.

I think we've made our points both on the technical and on the psyco-
sexual fronts

happy programming

jacob navia

unread,
Apr 21, 2010, 5:04:49 AM4/21/10
to
Michael Foukarakis a écrit :

> OK, let's revisit each point:
> - Is the library generic? Not if you have to preprocess it for each
> different data type you want to store. The void * approach/
> implementation, on the other hand, is.

Please, I have told many time in this discussion that the void *
approach is supported by the library. Additionally (and NOT instead of)
the library supports a templated form.

> - Is the library user friendly? Not if it introduces an extraneous
> step in the building process, which gives more room for errors and
> aggravates developers.

If preprocessing a template is too much for you, you can always
use the void * approach.

> - Is the library usable? Yes, if one ignores the above two points.
>

Thanks. The library is usable then, because it supports the void * approach.

For *me* the templated approach was necessary since I want to propose
a version of ALL containers for the standard data types of C
int, long long, double, long double, and character strings.

Templates allow me to build the bulk of the code for those with no
extra effort, and add a specialization when needed. Numeric containers
will support extra functions like "Accumulate", and the four operations
(element-wise)


>
> You misunderstood, again. The choice (or not) of a custom container
> like JNs in a purely academic discussion (such as this, so far) is
> irrelevant; the real question is what constraints does it operate
> under, what problems it solves (besides storing things in a black
> box), what benefits does it have over other container libraries. Do
> you still disagree?
>

Each container solves a particular problem. Bitstrings are good at
boolean operations, flexible arrays allow easy to use storage of
like-elements, trees allow you for fast searching, dictionaries allow
you easy searching for symbol tables, etc etc. Containers are a general
data structure and there is almost no application that doesn't use them
in some way.

bartc

unread,
Apr 21, 2010, 7:48:17 AM4/21/10
to
Michael Foukarakis wrote:

> - Is the library user friendly? Not if it introduces an extraneous
> step in the building process, which gives more room for errors and
> aggravates developers.

It sounds like this step is only done infrequently (when the template is
first applied to a new type), and not needed for every compile or build.

--
Bartc

io_x

unread,
Apr 21, 2010, 10:59:02 AM4/21/10
to
"Nick" <3-no...@temporary-address.org.uk> ha scritto nel messaggio
news:87ochej...@temporary-address.org.uk...

> jacob navia <ja...@nospam.org> writes:
> I didn't say "you would fail". I said "I don't see it taking off". Why
> do you always turn any comments into some sort of personal attack on
> yourself? It's very unbecoming. Nevertheless, wouldn't you be
> expecting some sort of widespread take-up by now if it was to be the
> success that every previous attempt has not been?

for me a good library
apply revolutionary ideas that make ok the point 1,2,3
0) good documentation with many examples
1) it is possible follow well the code, even in assembly [+ origin language]
2) is all easy
3) it has the size in bytes < 1/1000 than C library
less verbose to use, complete,
using same way of pass arguments or congruent with itself
with very good error catching

only one extraterrestrial could write it :)

but even if such library exist
i would prefer write all functions myself
like someone of you say: reinventing the hot water
but what i say is not important because i'm not the "crowd"
i'm only one with differents ideas from other peoples

lawrenc...@siemens.com

unread,
Apr 21, 2010, 12:15:42 PM4/21/10
to

Not off hand. I don't think qsort is generally considered a common
bottleneck deserving of special optimization.
--
Larry Jones

Who, ME? Who?! Me?? WHO... Me?! Who, me??? -- Calvin

0 new messages