C needs a BOOST

K

Keith Thompson

jacob navia said:
user923005 wrote: [...]
I used this very technique in the source code for chapter 13 of "C
Unleashed".
I called it PRELUDE instead of PREFIX.
Interesting , Mr "user923005". So you are Heathfield. It seemed to me
that both "you" and "he" are the same. I wonder how many of the
c.l.c "regulars" are just the same guy!

You might take note of the fact that amazon.com lists 16 authors for
"C Unleashed":

Richard Heathfield
Lawrence Kirby
Mike Lee
Mathew Watson
Ben Pfaff Peter Seebach
Brett Fishburne
Scott Fluhrer
Ian Woods
Sam Hobbs
Ian Kelly
Mike Wright
Chad Dixon
Stephan Wilms
Jack Klein

and that user923005's e-mail address is <[email protected]>.

Ironically, all the regulars *except* user923005 are really Richard
Heathfield. Richard Heathfield himself is of course Spartacus.
 
P

Paul Hsieh

A part of C did escape, then it morphed into C++....

So what you are saying, is that if you wish to gain access to well
tested polished implementations of generic abstract data structures
then you have buy into and endorse "RAII" ("Resource Acquisition Is
Initialization"; the C++ way of doing things.) Otherwise you have to
spend many man years making your own in C (or compromise on quality
somehow)?

You know there are some people in this world who think C++ is a bit
too heavy, onerous, and just not quite right (did you know that STL's
vectors require that your class have an empty constructor and that
this empty constructor will be called on free spaces in the vector
array before a real overwriting copy operation happens?). People who
think that making high quality libraries in pure C might be a good
idea:

http://sglib.sourceforge.net/
http://www.pcre.org/
http://bstring.sf.net/

Your argument (and you are obviously not alone in this, as this thread
is ample evidence of) is that the efforts above are not a direction
worth pursuing. That C by itself just isn't the right language for
implementing standard generic libraries for common data structures.

And you use this as a standard cut and paste argument for any
statement that criticizes weaknesses in the current C standard.
 
I

Ian Collins

Paul said:
So what you are saying, is that if you wish to gain access to well
tested polished implementations of generic abstract data structures
then you have buy into and endorse "RAII" ("Resource Acquisition Is
Initialization"; the C++ way of doing things.) Otherwise you have to
spend many man years making your own in C (or compromise on quality
somehow)?
No, I said nothing of the sort.

I said that there was a fork in C which evolved into C++. Most of the
proposals for language extensions we see here would end up following the
same path.
You know there are some people in this world who think C++ is a bit
too heavy, onerous, and just not quite right.

Did I claim otherwise?
People who
think that making high quality libraries in pure C might be a good
idea:

http://sglib.sourceforge.net/
http://www.pcre.org/
http://bstring.sf.net/

Your argument (and you are obviously not alone in this, as this thread
is ample evidence of) is that the efforts above are not a direction
worth pursuing. That C by itself just isn't the right language for
implementing standard generic libraries for common data structures.
Nonsense. I said that if there had been a strong demand for standard
generic libraries in C they would have found their way into the standard
by now.
And you use this as a standard cut and paste argument for any
statement that criticizes weaknesses in the current C standard.
Do I? I have never claimed that C isn't the right language for
implementing standard generic libraries for common data structures, just
that no one has produced a sufficiently popular implementation to evolve
into a standard.
Your sig is still broken.
 
J

James Kuyper Jr.

Paul Hsieh wrote:
....
You know there are some people in this world who think C++ is a bit
too heavy, onerous, and just not quite right (did you know that STL's
vectors require that your class have an empty constructor and that
this empty constructor will be called on free spaces in the vector

By "empty constructor" do you mean a "default constructor"? That's only
required if you use one of the vector constructors that uses the default
constructor. If you create a vector that is empty, or initialized with N
copies of a specified object, or is initialized from an iterator range,
the default constructor is not required.
 
P

Paul Hsieh

Paul Hsieh wrote:
...

By "empty constructor" do you mean a "default constructor"? That's only
required if you use one of the vector constructors that uses the default
constructor. If you create a vector that is empty, or initialized with N
copies of a specified object, or is initialized from an iterator range,
the default constructor is not required.

And what if you need to add entries to this vector over time? Looking
at the *implementations* of a few STLs, it seems to me that for
efficiency reasons, they pretty much need to default constructor to be
there. This is one of the problems with RAII -- you cannot prepare
space for your objects asynchronously from their initialization, so
you are forced to initialize them twice; the first time being
knowingly irrelevant.
 
I

Ian Collins

Paul said:
And what if you need to add entries to this vector over time? Looking
at the *implementations* of a few STLs, it seems to me that for
efficiency reasons, they pretty much need to default constructor to be
there. This is one of the problems with RAII -- you cannot prepare
space for your objects asynchronously from their initialization, so
you are forced to initialize them twice; the first time being
knowingly irrelevant.
What? You most certainly do not have to initialise objects twice.

What do vectors have to do with RAII anyway?
 
J

J. J. Farrell

Interesting , Mr "user923005". So you are Heathfield. It seemed to me
that both "you" and "he" are the same. I wonder how many of the
c.l.c "regulars" are just the same guy!

How on earth did you make that remarkable leap of logic?
 
K

Keith Thompson

J. J. Farrell said:
user923005 wrote: [...]
I used this very technique in the source code for chapter 13 of "C
Unleashed".
I called it PRELUDE instead of PREFIX.

Interesting , Mr "user923005". So you are Heathfield. It seemed to me
that both "you" and "he" are the same. I wonder how many of the
c.l.c "regulars" are just the same guy!

How on earth did you make that remarkable leap of logic?

Presumably he knows that Richard Heathfield is an author of "C
Unleashed", but didn't realize that there are several other authors as
well (and didn't bother to check before making the accusation).
 
M

Malcolm McLean

Ian Collins said:
What? You most certainly do not have to initialise objects twice.

What do vectors have to do with RAII anyway?
If using STL you need to provide a default / empty constructor and a copy
constructor for every class. Otherwise the system will rapidly gum up.

It can be a problem because the whole point of the constructor / destructor
/ method paradigm is to make use that every class is valid. However it only
sometimes makes sense to have default objects. A default image, for
instance, might be 0 by 0 dimensions, but if you are not careful then you'll
introduce errors by having a null for the raster data, when in the context
of the program it doesn't make any sense to have zero-dimensioned images
anyway.
 
I

Ian Collins

Malcolm said:
If using STL you need to provide a default / empty constructor and a
copy constructor for every class. Otherwise the system will rapidly gum up.
Or not compile. What do you expect from a container? The semantics of
a vector are pretty similar to an array, where objects also have to have
a public copy constructor. In practice, C++ standard containers tend to
be used to store PODs, small objects or pointers.
It can be a problem because the whole point of the constructor /
destructor / method paradigm is to make use that every class is valid.

So if you declare a vector of 10 objects, what would you rather have, 10
default initialised objects, or garbage? If an object can't be default
initialised, it probably has no place being in a container.
However it only sometimes makes sense to have default objects. A default
image, for instance, might be 0 by 0 dimensions, but if you are not
careful then you'll introduce errors by having a null for the raster
data, when in the context of the program it doesn't make any sense to
have zero-dimensioned images anyway.
No one would store images in a container you would store pointers, or
back on the sub-thread subject of RAII, a smart pointer to one.
 
J

James Dennett

Malcolm said:
If using STL you need to provide a default / empty constructor and a
copy constructor for every class.

This is emphatically not the case, and deliberately so. Many
people use the STL extensively with many classes which do not
permit default construction. It works where appropriate.
Otherwise the system will rapidly gum up.

Not really.
It can be a problem because the whole point of the constructor /
destructor / method paradigm is to make use that every class is valid.
However it only sometimes makes sense to have default objects. A default
image, for instance, might be 0 by 0 dimensions, but if you are not
careful then you'll introduce errors by having a null for the raster
data, when in the context of the program it doesn't make any sense to
have zero-dimensioned images anyway.

Which is why the STL works hard *not* to require default
constructors when it can be avoided.

-- James
 
R

Richard Heathfield

Keith Thompson said:
J. J. Farrell said:
user923005 wrote: [...]
I used this very technique in the source code for chapter 13 of "C
Unleashed".
I called it PRELUDE instead of PREFIX.

Interesting , Mr "user923005". So you are Heathfield. It seemed to me
that both "you" and "he" are the same. I wonder how many of the
c.l.c "regulars" are just the same guy!

How on earth did you make that remarkable leap of logic?

Presumably he knows that Richard Heathfield is an author of "C
Unleashed", but didn't realize that there are several other authors as
well (and didn't bother to check before making the accusation).

This is a recurring problem with Jacob Navia's articles. He asserts
something that he (presumably) believes to be true, but without checking
his facts. Because he believes it to be true, he cannot understand why
people disagree with him, and assumes that it must surely be because they
are either ignorant or hostile, so he reacts with hostility. At least,
that is my best guess. I can think of no other rational explanation
(although perhaps others here /can/ do so).

His advertising of his compiler within this non-commercial newsgroup seems
to have diminished to the point where it is no longer a significant issue.
If we can educate him to do that, perhaps we can also educate him to check
his facts before making claims, at which point he might yet become a
valuable member of the group.

Well, you never know your luck, do you?
 
C

Charlie Gordon

Keith Thompson said:
That "," should be "+", yes?


So you provide a function that converts an integer to a string:

"hello " + audience + "time left " + image(hours) + image(minutes) + "\n";

If we want to travel this road, why not go the whole nine yards and support
a more readable syntax:

"hello $audience, time left $hours:$minutes\n";
 
C

Charlie Gordon

Malcolm McLean said:
Now you've introduced a requirement for automatic garbage collection.
It's the approach I used in MiniBasic, but then it was never sold as a
fast, low-level language.

A temporary string object is indeed constructed above, and could be disposed
of without full blown garbage collection. string management would be
needed, maybe with reference counting.
 
C

Charlie Gordon

jxh said:
As stated in the quoted material, it is for compatibility with
C++, but also to lessen the burden of introducing the feature
into C compilers.

Compatibility with C++ may not be desirable at the syntax level, if the
semantics differ.
Syntactic choices have little impact on compiler complexity. Introducing
templates in C by transplanting a C++ implementation is hopeless.
 
J

James Kuyper Jr.

Paul said:
And what if you need to add entries to this vector over time? Looking
at the *implementations* of a few STLs, it seems to me that for
efficiency reasons, they pretty much need to default constructor to be
there.

To add entries to your vector:

1. If doing so would require more space than is currently allocated,
allocate more space.

2. If the extra entries are being added anywhere but at the end of the
vector, you need to copy existing entries to new locations to make room
for the new entries, and to destroy existing entries to make room for
the objects that will be copied. I'm not familiar with the new "move
semantics" that are being considered for the next version of the C++
standard, but I presume that the existing entries might be moved rather
than copied and destroyed, where appropriate.

3. The new entries are then copied into the space reserved for them.

I don't see any need for the default constructor here. Certainly not for
efficiency's sake: adding calls to a default constructor at any place in
the above sequence would merely require corresponding calls to the
destructor, wasting time both ways.

The exception, of course, is if you want to insert new
default-constructed entries. That's precisely the point. None of the
standard containers requires that the contained type be default
constructible, unless you use those members which construct/insert
default-constructed elements into the container. That seems a very
reasonable way of handling it, and I don't see how mentioning that fact
qualifies as a criticism of the C++ standard containers.
This is one of the problems with RAII -- you cannot prepare
space for your objects asynchronously from their initialization, so
you are forced to initialize them twice; the first time being
knowingly irrelevant.

I don't what you're talking about. Every standard C++ container class
has an allocator class associated with it, either by explicitly using
std::vector<T,Allocator>, or by letting Allocator default to
std::allocator<T>.

Creating space for your objects asynchronously from their initialization
is precisely what the Allocator class is for. The Allocator::allocate()
function creates the space, without calling the constructor. The
Allocator::construct() function calls the appropriate constructor,
without having to allocate the space. The Allocator::destroy() function
calls the appropriate destructor, without deallocating the space. The
Allocator::deallocate() function releases the space, without calling the
destructor.

Calling std::vector::reserve() is the way for the end user to trigger a
call to Allocator::allocate(), if needed to reserve space for the
requested number of elements. One of the few criticisms I have of
std::vector is that calling reserve() with a value smaller than the
current value of capacity() is not guaranteed to make the appropriate
call to Allocator::deallocate().
 
C

Charlie Gordon

Szabolcs Nagy said:
/* generic_qsort.c */
PREFIX(qsort)(TYPE *arr, size_t len) {
...
if (LESS(*right, pivot)) {...}
...
}


/* int_qsort.c */
#define PREFIX(s) int_##s
typedef int TYPE;
static inline int LESS(int a, int b) {return a < b;}
#include "generic_qsort.c"
#undef PREFIX

not much longer than c++ templates imho
macros are ugly though

generic)qsort is not generic enough: the LESS function and the TYPE typename
should be macroized with PREFIX as well, to allow for multiple
instantiations of generic qsort routines for different types in the same
module.

/* generic_qsort.c */
void PREFIX(qsort)(PREFIX(TYPE) *arr, size_t len) {
...
if (PREFIX(LESS)(*right, pivot)) {...}
...
}

/* mymodule.c */
#define PREFIX(s) int_##s
typedef int int_TYPE;
static inline int int_LESS(int a, int b) {return a < b;}
#include "generic_qsort.c"
#undef PREFIX
....
#define PREFIX(s) string_##s
typedef const char * string_TYPE;
static inline int string_LESS(const char *a, const char *b) {return
strcmp(a, b) < 0;}
#include "generic_qsort.c"
#undef PREFIX

TYPE, LESS and QSORT could be made macros themselves, with a similarly ugly
implementation/instantiation:

/* generic_qsort.c */
void QSORT(TYPE *arr, size_t len) {
...
if (LESS(*right, pivot)) {...}
...
}

/* mymodule.c */
#define QSORT int_qsort
#define TYPE int
#define LESS(a, b) ((a) < (b))
#include "generic_qsort.c"
#undef PREFIX
#undef TYPE
#undef QSORT
....
#define QSORT string_qsort
#define TYPE const char *
#define LESS(a, b) (strcmp(a, b) < 0)
#include "generic_qsort.c"
#undef PREFIX
#undef TYPE
#undef QSORT

Some better mechanism would certainly help writing type safe generic code:

/* hypothetical example */
/* generic_qsort.h */
template generic_qsort(qsort, type, isless) {
typedef type;
int isless(type a, type b);
void qsort(type *arr, size_t len) {
...
if (isless(*right, pivot)) {...}
...
}
}

/* mymodule.c */
#include "generic_qsort.h"

static inline int int_less(int a, int b) {return a < b;}
static inline int string_less(const char *a, const char *b) {return
strcmp(a, b) < 0;}
generic_qsort(int_qsort, int, int_less);
generic_qsort(string_qsort, const char *, string_less);
 
U

user923005

J. J. Farrell said:



Rover is a dog. Fido is a dog. Therefore, Rover is Fido.

This one's funnier:
All men are mortal. All women are mortal. Therefore, all men are
women.
 

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
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top