C needs a BOOST

S

santosh

jacob said:
Look. Let's NOT redo C++. C is simple. If you want
"the whole enchilada"... then program in C++ of course.

C and C++ remain distinct languages. C keeps things simple
and is fast, C++ has other uses, and can be as fast as C
sometimes.

The most sensible thing you've said in a while. :)
 
J

jxh

Note I'm not proposing the addition, it's just that RAII is
the one thing I miss most when swapping from C++ to C. Just
about everything else can be worked around in standard C. The
closest equivalent I know of is pthreads cleanup handlers.
Maybe something along those lines might be a more acceptable
extension to C?

I had wondered about the feasibility of an "at_return()" API,
analog to "at_exit()", but it is hard to write functions that
handle cleanup without access to the local variables of the
function that is about to return.

The availability of template functions may alleviate that
problem, however.

template <FILE *fp>
void close_file_pointer () { fclose(fp); }

void foo () {
FILE *input = fopen("inputfile", "r");

at_return(close_file_pointer<input>);

/* ... */
}

-- James
 
K

Keith Thompson

Default User said:
You don't seem very friendly.

I hereby declare this subthread terminated, by virtue of my authority
-- oh, wait, I don't have any. Well, I declare this subthread
terminated anyway.

Come on, guys, play nice.
 
J

jxh

.... some drivel ...

The example doesn't work in C++, since a constant value is required to
be passed to templates that take a value as an argument.

-- James
 
E

Ed Jensen

In comp.lang.c Ian Collins said:
Which raises the question why hasn't anyone written such a popular
library for C? C has been around a decade or more longer than C++,
plenty of time for a "killer library" to appear, but it hasn't.

My conclusion has to be that the demand isn't there.

I think your conclusion is wrong.

My conclusion is that many developers chose to move to less primitive
languages with more comprehensive standard libraries instead.
 
I

Ian Collins

Ed said:
I think your conclusion is wrong.

My conclusion is that many developers chose to move to less primitive
languages with more comprehensive standard libraries instead.

It what way does that contradict my conclusion?
 
R

Richard Heathfield

Keith Thompson said:
Then why do you want to change C at all?

To lock people into lcc-win32, and to turn comp.lang.c into his own
personal advertising hoarding. Really, Keith, didn't you know that?
Yes, I know, you want to "improve" C without bringing in all of C++.
But it's by no means obvious *which* features are most important.

The *most* important feature for C is one that it already possesses, and
which significant changes would damage: portability. The language already
permits extensions for vendors who wish to provide them, and third-party
libraries for those who wish to write them.
 
C

Chris Thomasson

Eric Sosman said:
Chris Thomasson wrote On 10/05/07 06:14,:

Perhaps it might be too ambitious to begin with
something as advanced as a stack.

Lest start off with the small stuff... A LIFO is not advanced; at least that
the way it is imo...

If we cannot break a LIFO down into a minimial (e.g. macro level) API like I
have in mind:

<pseudo-code>
_______________________________
typedef struct clc_slink_s clc_slink;

struct clc_slink_s {
clc_slink* nx;
};

CLC_SLIST_STATIC_INIT(...); /* static initialization */
void clc_slist_init(...); /* dynamic initialization */
void clc_slist_push(...); /* push a link */
slink* clc_slist_pop(...); /* pop a link */
_______________________________


We have problems indeed! Anyway;

The macro API level represents the basic interface for the job at hand...
Extensions would represent a micro API level down below the macro... Sort of
like the following C++ analog:

http://groups.google.com/group/comp.lang.c++.moderated/msg/bb45c17cdd3c04a3
 
C

Chris Thomasson

[...]
<pseudo-code>
_______________________________
typedef struct clc_slink_s clc_slink;

struct clc_slink_s {
clc_slink* nx;
};

CLC_SLIST_STATIC_INIT(...); /* static initialization */
void clc_slist_init(...); /* dynamic initialization */
void clc_slist_push(...); /* push a link */
slink* clc_slist_pop(...); /* pop a link */
^^^^^^^^^^^^^

clc_slink* clc_slist_pop(...); /* pop a link */

_______________________________


I will post workable/compliable code sometime tomorrow.
 
C

Chris Thomasson

Richard Heathfield said:
[followups set to comp.lang.c]

Chris Thomasson said:

void clc_slist_init(...); /* dynamic initialization */

Where is the "graceful failure" mechanism?

Okay... We could do this:


<pseudo-code>
_________________________________________________

/*
typedef struct clc_slink_s clc_slink;

struct clc_slink_s {
clc_slink* nx;
};
*/


/* returns 'nx' param;
- returns NULL on failure */
clc_slink* clc_slist_init(
clc_slink* const _this,
clc_slink* const nx
) {
_this->nx = nx;
return nx;
}


-------------------------------------------
/* returns 'link' param;
- returns NULL on failure */
clc_slink* clc_slist_push(
clc_slink* const _this,
clc_slink* const link
) {
if (link) {
link->nx = _this->nx;
_this->nx = link;
}
return link;
}
_________________________________________________




Now we can do stuff like:
_________________________________________________
typedef struct my_node_s my_node;

struct my_node_s {
clc_slink slink;
[...];
};

static clc_slink mylist = CLC_SLIST_STATIC_INIT(0);

/* returns NULL on failure */
my_node* my_node_produce(...) {
my_node* const _this =
clc_slist_push(&mylist, malloc(sizeof(*_this)));
return _this;
}
_________________________________________________

[...]


Any better?
 
C

Chris Thomasson

[...]
static clc_slink mylist = CLC_SLIST_STATIC_INIT(0);

/* returns NULL on failure */
my_node* my_node_produce(...) {
my_node* const _this = ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
clc_slist_push(&mylist, malloc(sizeof(*_this)));
return _this;
}
_________________________________________________



Ouch! We need a cast for the code above to compile correctly; like this:
_________________________________
my_node* const _this =
(my_node*)clc_slist_push(&mylist, malloc(sizeof(*_this)));
_________________________________





Okay... We can have the 'clc_slist_push/init' functions return 'void*' in
order to do away with the casting; here is the "fresher/newer" proposed API:
_______________________________
typedef struct clc_slink_s clc_slink;

struct clc_slink_s {
clc_slink* nx;
};

CLC_SLIST_STATIC_INIT(...); /* static initialization */
void* clc_slist_init(...); /* dynamic initialization; returns NULL on
failure. */
void* clc_slist_push(...); /* push a link; returns NULL on failure. */
clc_slink* clc_slist_pop(...); /* pop a link */
_______________________________





Now, using that interface, the following code will work:
_______________________________
typedef struct my_node_s my_node;

struct my_node_s {
clc_slink slink;
[...];
};

static clc_slink mylist = CLC_SLIST_STATIC_INIT(0);

/* returns NULL on failure */
my_node* my_node_produce(...) {
my_node* const _this =
clc_slist_push(&mylist, malloc(sizeof(*_this)));
return _this;
}
_______________________________




We should keep in mind that the more features we add, the more we move away
from the minimalist nature of the original proposal... I am sure this LIFO
API can be realized. IMVHO, we need to try and maintain a fairly high-level
of patience before we get into an all out flame war here...

;^)
 
C

Chris Thomasson

[...]
Okay... We can have the 'clc_slist_push/init' functions return 'void*' in
order to do away with the casting; here is the "fresher/newer" proposed
API:
[...]

I think I will post the proposal/example code/api under the following
subject:


'The CLC Standard: LIFO Collection API Proposal'
 
M

Malcolm McLean

Chris Thomasson said:
Lest start off with the small stuff... A LIFO is not advanced; at least
that the way it is imo...
I'd advise you to start off with a red black tree or a hash table.

Everyone can write their own linked list routines or stacks, and the
benefits of yours aren't obvious. However a more complex structure takes
non-trivial effort to code, so you've got a much better chance of
acceptance. After the complex structures have some sort of following, people
might accept linked lists or dynamic arrays that operate with the same
conventions. But they are not going to rewrite their code tomorrow just
because CT says "we should have a fucntion called clc_llunlink() to remove a
node from a linked list".
 
A

André Gillibert

jacob said:
Wow, that would be C++.

Yes. It would just be (C++ - a few things)
+ many_useless_incompatibilities.

Constructors and destructors look simple but are HELL to implement:

int foo(int n)
{
int arg;
// ...
if (arg > 0)) {
struct foo;
// ... some code
goto exit;
// ... some code
}
exit:
return 56;
}

The destructor of foo needs to be called before the goto gets
executed... This was a bug still in MSVC some years ago.

Wow. I find it hard to believe that a commercial application was so buggy,
while this is the first thing I would have thought of!
Anybody with a brain, when implementing constructors and destructors,
starts by thinking about:
1) What are the scope and lifetimes of objects.
2) What are the ways to enter and exit these scopes (such as return, goto,
break, continue, longjmp, C++ exceptions) and what to do in each case.

Now, I don't doubt of the incompetence of MSVC programmers.
 
M

Malcolm McLean

Douglas A. Gwyn said:
The advantage of having a committee of experience experts
deciding on Standard C's direction is that there is balance
so that more relevant factors get considered before changes
are made. The net newsgroups have seen many people who think
that obviously they know best how things should be done and
that any other ideas are wrong-headed. Fortunately that is
not how C has evolved.
Some things can't be done by committee. For instance I don't think there is
a single example of a famous poem written by a committee of people.

Language design is another of those things that don't seem to respond well
to committee treament. The mentality of a brilliant software designer and a
good committee member seem to be opposed. The reason is that a successful
language is usually a cloaking of a simple, radical idea with usable syntax,
without compromises. Committee members by nature compromise with each other.
Most language designs are not too successful. For instance my idea of
MiniBasic - 1980s style BASIC as an embedded script, on the basis that there
is a base of millions of amateur BASIC programmers - hasn't caught on as I
had hoped. But it might have worked.
 
M

Malcolm McLean

Mark McIntyre said:
Just to complement this: the original remark was absurd - nobody
rewrites everything from scratch at each new project - and the poster
knew it. Its exactly this kind of foolish remark that gives people a
bad reputation as posters.
That's not true in games.
What typically happens in a games company is that a product is released. If
it is successful, the graphics will be changed and a few tweaks and twiddles
made to the code, to get something that plays rather differently and looks
new to the user but costs less to develop. After about the third time round
the whole thing is getting creaky, the programmers are getting bored, and
technology has moved on. So management decide to invest in a new version,
"starting with a clean sheet".

All the code from the old version will be rigorously thrown away, and every
single line rewritten from scratch, for a brand new project. It is largely
psychological, to do something new rather than rehash the old game.
 
A

André Gillibert

jacob said:
How do you get rid of the goto?

int Search_byName(char *name,int HowtoSearch)
{
switch(HowtoSearch) {
// ...
case 42:
for (int i=0; i<Len; i++) {
if (!strcmp(name,nameTab))
goto found; // <<<<--
}
fprintf(stderr,
"Not found\,%s is an illegal name);
return 0;
case 65:
// ...
}
return -1;
found:
// Some code
return 1;
}


Goto allergic people will say that you just can:
1) Define a boolean indicating the type of exit of the switch statement.
Something like:

_Bool error=1;
switch(HowtoSearch) {
case 42:
for (int i=0; i<Len; i++) {
if (!strcmp(name,nameTab))
{error=0;break;}
}
case 65:
/* ... */
}
if (error) return -1;
/* Some code */

2) Move the "return -1;" statement to everywhere you exit the switch
normally (e.g. with break). For more complex conditions, a separate
function should be implemented to do the work so that the statement
becomes: return FunctionCall(...);
(Personally, I would find it harder to maintain and dangerous not to
forget one exit case).

Note: In the set of goto allergic people, there's the subset of
goto/continue/break/short-return allergic people.
They use many boolean variables to do things such as;
for(i=0; i<n && !exit_from_loop; i++) {
/* ... */
if (condition) {exit_from_loop=1;}
else {
/* ... */
}
}

The break statement has no arguments, and for breaking out
of several nested scopes you *have* to use gotos.

Or boolean variables (which typically has an overhead for nested loops).
 
A

André Gillibert

jacob said:
int foo(int n)
{
int arg;
// ...
if (arg > 0)) {
struct foo;
// ... some code
goto exit;
// ... some code
}
exit:
return 56;
}

The destructor of foo needs to be called before the goto gets
executed... This was a bug still in MSVC some years ago.

Just by curiosity, had MSVC bugs (such as silently compiling and not
initializing the variable) when entering a scope with a goto or switch
case?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top