Topic: Standard component library


Author: Stephen G. Edwards <edwards@kong.gsfc.nasa.gov>
Date: 1 Jun 1993 18:58:09 GMT
Raw View
In article <1993May24.173108.24095@microsoft.com> Jim Adcock,
jimad@microsoft.com writes:
>In article <edwards-210593095041@sedwards.gsfc.nasa.gov>
>edwards@kong.gsfc.nasa.gov (Stephen G. Edwards) writes:
>|   PtrList - holds pointers, does not own the object pointed to
>|   DeepList - holds pointers, but DOES own the object pointed to
>|
>|Copying or destroying a DeepList will also copy and destroy its contents,
>|respectively.  A PtrList just copies or throws away its pointers.
>|
>|Redundant?  Sure, but so what.
>
>So what?  So your example shows that lack of GC defeats the concept
>of generally reusable container classes.  As opposed to the other
>OOPLs that *have* GC, and also have standard, reusable container
>classes.  These C++ restrictions that one and only one container class
>*owns* the object, and the rest merely reference the object cannot
>be a robust general purpose situation.  Managing the lifetime of an
>object becomes a global concern when it should only be a local concern --
>in general all the "referencing" containers must worry that the owning
>container keep this object alive during the lifetime of the "referencing"
>container.

I think you read more into my "so what?" than intended, but that's OK, it's
interesting.  I'm just trying to deal with the problem of memory management in
a sane manner.  For me, far more important than any particular feature (or
lack thereof) of any programming language is the ability of my developers to
communicate with one another and the machine unambiguously.  The "two-list"
approach has worked amazingly well in that respect.

>  This is an awfully constrained model of membership compared
>to the situations we need to model in real life.  As opposed to GC,
>which allows objects to exist in as many memberships as required by
>a program, those memberships existing as long as need be, and "ownership"
>of the object shared among the containers as long as they need ownership.

Actually, I've found that in modeling an application domain, more often than
not objects DO have a permanent home in one place and reside only temporarily
in all other contexts.  GC seems to me to be an implementation convenience,
not a specification tool.

>It continues to amaze me how hard C++ programmers are willing to make
>these issues, simply for the lack of a real GC implementation.

On the contrary, I thought our approach, although arguably simple-minded, was
rather straightforward and intuitive.  It has made an implicit constraint of
C++ explicit and has allowed us to get on with our lives and concentrate on
more application-specific problems.

---
Stephen G. Edwards                     email: edwards@kong.gsfc.nasa.gov
Code 522.2                             phone: (301) 286-6676
NASA/Goddard Space Flight Center         fax: (301) 286-4627
Greenbelt, MD  20771




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Mon, 24 May 1993 09:45:32 GMT
Raw View
tmb@arolla.idiap.ch (Thomas M. Breuel) writes:

>>>>>> On Sun, 23 May 1993 22:20:52 GMT, djones@megatest.com (Dave Jones) said:
>> I would prefer not to have container classes that let the internal memory
>> pointers leak out and then invalidate them, even if they are documented not
>> to be valid after the next time the container is accessed. I think that
>> is asking for trouble.
>
>That is a general problem with C++: "internal memory pointers" can
>"leak out" all over the place in C++ programs.

Yes, you are right, this is a general problem with C++.

>The solution you propose, making internal addresses of data structure
>not be lvalues is not necessarily very effective, but it is quite
>cumbersome.  In particular, passing a location by reference is a
>frequent and safe operation, as is assigning to some internal
>location.
>
>I think a better solution than to simply avoid exposing all lvalues is
>not to use the address-of operator.  With reference types, the need to
>do so has been greatly diminished.  And, if you forsake use of the
>address-of operator, you are safe from unintentionally keeping
>pointers not only to the guts of your own data structures, but also to
>the guts of third party data structures, old-style C data structures,
>and even automatic variables.

I agree that it's good practice to avoid using address-of in C++ where
possible, but it doesn't solve the problems.
It might stop dangling pointers, but it doesn't stop dangling references.
Consider:
 int & foo() {
  int x = 0;
  return x; // return reference to local variable
 }
Well, many compilers will warn about that one. However they won't get
the more complicated cases, eg.
 int & foo() {
  Map<char *,int> map;
  return map["foo"];
 }
And this is not to even mention difficulties with references to temporaries...

--
Fergus Henderson                     This .signature virus might be
fjh@munta.cs.mu.OZ.AU                getting old, but you still can't
                                     consistently believe it unless you
Linux: Choice of a GNU Generation    copy it to your own .signature file!




Author: tmb@arolla.idiap.ch (Thomas M. Breuel)
Date: 24 May 93 14:54:53
Raw View
>>>>> On Mon, 24 May 1993 09:45:32 GMT, fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) said:
>>I think a better solution than to simply avoid exposing all lvalues is
>>not to use the address-of operator.  With reference types, the need to
>>do so has been greatly diminished.  And, if you forsake use of the
>>address-of operator, you are safe from unintentionally keeping
>>pointers not only to the guts of your own data structures, but also to
>>the guts of third party data structures, old-style C data structures,
>>and even automatic variables. [goes on to mention Ellis and Detlefs]
>
> I agree that it's good practice to avoid using address-of in C++ where
> possible, but it doesn't solve the problems. [...] However they won't get
> the more complicated cases, eg.
>  int & foo() {
>   Map<char *,int> map;
>   return map["foo"];
>  }

You are right that it doesn't solve all problems.  But if you don't
use address-of, you are guaranteed that all bad pointers (rather than
references) are due to using "delete" poorly.  And that you can avoid
by using reference counting or GC.

In fact, an insidious problem still persists even if you just use
references.  Assume that "SelfGrowingArray" reallocates its internal
C-style array when the array grows.  Then, you can easily and
unexpectedly get a dangling reference if you do the following:

 SelfGrowingArray<int> array;

 void f(int &x) {
  array[100]=0;
  // "array" grows, "x" is now a dangling reference...
 }

 main() {
  array[0]=0;
  f(array[0]);
 }

In this case, you may want to have "array[0]" return some object that
can be assigned to, but that cannot be converted to a reference.

Indeed, not even garbage collection saves you from this problem.
Garbage collection might help you avoid making "x" a dangling
reference, but it would still refer to the wrong internal array.

In some sense, this is really a problem with the use of side
effects, not with pointers or references, since you can get
completely analogous problems even in languages which have neither
internal pointers nor references of any kind.

     Thomas.




Author: grumpy@cbnewse.cb.att.com (Paul J Lucas)
Date: Mon, 24 May 1993 14:19:48 GMT
Raw View


Author: steve@taumet.com (Steve Clamage)
Date: Mon, 24 May 1993 15:57:17 GMT
Raw View
grumpy@cbnewse.cb.att.com (Paul J Lucas) writes:

>>  typedef Y::String String;

> Is there any reason why the above typedef can't be used instead
> of introducing the "using" keyword?  This makes more sense and
> seems more orthogonal to me.

The "using" keyword is primarily intended to introduce a whole namespace
into a scope.  The namespace can include types (classes), constants,
functions, and variables.  You can make a whole library conveniently
available without needing to call out individual members.  If the
implementation of the library changes, you don't have to review all your
typedefs.
--

Steve Clamage, TauMetric Corp, steve@taumet.com




Author: jimad@microsoft.com (Jim Adcock)
Date: 24 May 93 17:31:08 GMT
Raw View
In article <edwards-210593095041@sedwards.gsfc.nasa.gov> edwards@kong.gsfc.nasa.gov (Stephen G. Edwards) writes:
|   PtrList - holds pointers, does not own the object pointed to
|   DeepList - holds pointers, but DOES own the object pointed to
|
|Copying or destroying a DeepList will also copy and destroy its contents,
|respectively.  A PtrList just copies or throws away its pointers.
|
|Redundant?  Sure, but so what.

So what?  So your example shows that lack of GC defeats the concept
of generally reusable container classes.  As opposed to the other
OOPLs that *have* GC, and also have standard, reusable container
classes.  These C++ restrictions that one and only one container class
*owns* the object, and the rest merely reference the object cannot
be a robust general purpose situation.  Managing the lifetime of an
object becomes a global concern when it should only be a local concern --
in general all the "referencing" containers must worry that the owning
container keep this object alive during the lifetime of the "referencing"
container.  This is an awfully constrained model of membership compared
to the situations we need to model in real life.  As opposed to GC,
which allows objects to exist in as many memberships as required by
a program, those memberships existing as long as need be, and "ownership"
of the object shared among the containers as long as they need ownership.

It continues to amaze me how hard C++ programmers are willing to make
these issues, simply for the lack of a real GC implementation.




Author: jimad@microsoft.com (Jim Adcock)
Date: 24 May 93 17:39:23 GMT
Raw View
In article <9314223.28075@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
|C++ has serious problems trying to support moveable objects, since
|in C++ the address of an object is its identity.  (Note the lack of a
|'renew' in C++.)

I disagree both that C++ has serious problems trying to support moveable
objects, and that the address of an object is its identity.

Regards the first issue, A C++ implementation that moves objects remains
conforming if it meets the requirements of the language.  The only
questionable item in this regard, as has been discussed many times,
is the cast to/from int, which is strictly implementation dependent in C,
and has this bogus "implementations that are big enough" requirement in C++.
Since the implementation defines the machine, my claim is that in C++
an implementation could simply declare "in this implementation ints aren't
big enough" and then could implement moveable objects.  Note that in reality,
a great variety of C/C++ operating systems, language implementations, and
hardware *ARE* implementing moveable objects, they are simply implementing
moveable objects in such a way as to remain generally transparent to the
programmer, who then fails to even think about these issues as being
"moveable objects".

In regards to whether or not addresses in C++ correspond to object
identities, below find a simple counterexample:

#include <stdio.h>

class A
{
 int a;
};

class B : public A
{
 int b;
};

class C : public A
{
 int c;
};

class D : public B, public C
{
 int d;
};

main()
{
 D d;

 B* pb = &d;
 C* pc = &d;
 A* pab = pb;
 A* pac = pc;

 if (pab == pac)
  printf("pab == pac -- in C++ addresses DO correspond to"
   " object identity\n");
 else
  printf("pab != pac -- in C++ addresses DO NOT correspond to"
   " object identity\n");

 return 0;
}






Author: swf@tools3teradata.com (Stan Friesen)
Date: 24 May 93 18:08:03 GMT
Raw View
In article <C7I3Fy.G4t@megatest.com>, djones@megatest.com (Dave Jones) writes:
|> From article <9314223.28075@mulga.cs.mu.OZ.AU>, by fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON):
|> > swf@tools3teradata.com (Stan Friesen) writes:
|> >>I view a map as an associative array, I want it to act like one.
|>
|> Then you are defining a "memory provider", like an array. I have no
|> quarrel with that. It is not a single variable, but instead makes
|> visible to the client many internal variables, each of which can store a value.

If you define 'memory provider' as something that *looks* like it is
providing memory, even when it is not, then I suppose yopu are right.

|> I would prefer not to have container classes that let the internal memory
|> pointers leak out and then invalidate them, even if they are documented not
|> to be valid after the next time the container is accessed.

And, you are *still* missing my point.
Just because something *acts* like a pointer or reference does not mean
that it actually *is* one.

There is no *necessity* to make the internal memory pointers accessible,
even with my sugegsted syntax.  The operator[] does *not* have to return
an actual reference, it can return a 'wrapper' class.

The only reason to reveal the pointer is the issue of efficiency.

--
sarima@teradata.com   (formerly tdatirv!sarima)
  or
Stanley.Friesen@ElSegundoCA.ncr.com




Author: kanze@us-es.sel.de (James Kanze)
Date: 19 May 93 19:19:52
Raw View
In <C776u3.9A9@megatest.com>, Dave Jones writes:

|> From article <2549@tdbunews.teradata.COM>, by
|> swf@tools3teradata.com (Stan Friesen):

|> > ... And make sure each of them has an associated iterator class.
|> > [I prefer iterators based on the 'pointer' model - dereference to access
|> > the value, increment operator to go th the 'next' item].

|> There are some classes that are meant to more or less mimic "raw" memory.
|> A self-extending array is an example. For such as that, the incrementing
|> pointer is okay. The bargain with the array class is, you give me access
|> to memory which I will use as I please.

I don't think that the pointer model will work in general.  Obviously,
I shouldn't be allowed to modify the index part of a map, as this will
cause problems with most of the implementation models.

I think that first, one must distinguish between containers which
manipulate two types (and index, and the relevant data), and those
which have just one part (sets, or classes like stack, where the
relevant element is selected by historical context).

My feeling is that iterators should be first class objects (so that
they can be passed to other functions, etc.).  So they are really
selectors with a few extra functions, ie: increment, isFinished, etc.
(My personal classes use operator++ for increment, and have a member
function 'finished'.)  In the case where they refer to containers with
two elements, they should probably have a cast operator to the index
type.  This will allow loops of the following form:

 for ( MyClass::Iterator i( myObject ) ;
    ! i.finished() ;
    i ++ )
 {
  myObject[ i ] ...
 }

One should also specify behavior in cases where two or more iterators
are active simultaneously on the same object, and where the topology
of the object changes during iteration.
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung




Author: kanze@us-es.sel.de (James Kanze)
Date: 18 May 93 15:48:05
Raw View
In article <1t88na$elp@cville-srv.wam.umd.edu> krc@wam.umd.edu (Kevin
R. Coombes) writes:

|> In article <9313704.15852@mulga.cs.mu.OZ.AU> fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
|> >maxtal@physics.su.OZ.AU (John Max Skaller) writes:
|> >
|> >> What do *you* all want from the library?
|> >
|> >I would like a string class, a template fixed length array class (just like C
|> >arrays, except they have optional bounds checking), and a template dynamic
|> >array class (size is dynamically allocated at construction but thereafter
|> >remains fixed). A very simple template list class might also be good.
|> >If they're going to do a list class then they might as well do stack
|> >and queue classes, it's hardly any more work.
|> >And a map (associative array) class would be nice.
|> >
|> >These should all be concrete classes, I don't think there's any need
|> >for any virtual functions.
|> >

|> I almost agree. The strings, arrays, and lists should be concrete.
|> But there are times when I want a stack (or queue) to be implemented
|> as a list, and there are other times when I want it implemented as an
|> array. Are you sure there shouldn't be virtual functions?

I think you should separate the two aspects.  On one hand, you have
implementation classes, ie: array, list, etc.  On the other hand, you
have your abstract data types like stack and queue.

The implementation classes probably should not have virtual functions.

The basic abstract data type classes should be pure abstract classes,
with only pure virtual functions, and no data members.

The concrete instances of the abstract data types derive from the
basic abstract data types.  They contain an instance of the
implementation class.  The implementations of the virtual functions
are basically just forwarding functions to the implementation class.

Most functions manipulating stacks, queues, etc. will simply take a
reference to the basic abstract data type, and will work indifferently
whether for example, the stack is implemented as an array or as a
list.

(I do not think that the complete design will be as simple as it
appears above.  In particular, I think it will require a good deal of
though about how best to do iterators with such a scheme.  I rather
suspect some sort of envelope class will be called for.)
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung




Author: kanze@us-es.sel.de (James Kanze)
Date: 19 May 93 19:02:52
Raw View
In article <C76zC2.8L0@megatest.com> djones@megatest.com (Dave Jones)
writes:

|> From article <1993May16.095058.12107@ucc.su.OZ.AU>, by maxtal@physics.su.OZ.AU (John Max Skaller):
|> > In article <C73JJ0.GHI@megatest.com> djones@megatest.com (Dave Jones) writes:
|> >>From article <1993May14.172446.17635@ucc.su.OZ.AU), by maxtal@physics.su.OZ.AU (John Max Skaller):

|> >> ... I want the draft standard for the String class (so I can write a
|> >> conforming shell around an existing String class). Could someone please
|> >> post it?
|> >
|> >  That wasnt quite what I meant. What I meant was what do you want
|> > in a string class? Anyone out there: what do *you* want?

|> Oh. Well, I'm not completely sure, but I could get by initially with just the
|> basics: lists, queues, maps, graphs, et cetera. And oh yeah, regular
|> expressions.

|> I think I want the following properties. (I'm sure someone will tell
|> me where I am wrong.)

|> 0. Skinnny interfaces. Classes should be unintrusive. They
|> should not require that the objects they manipulate be derived from a
|> single do-everything base class. Which brings us to...

|> 3. For operator[], indexes always start at zero.

And if the index is of type String?  For that matter, I would like to
see an array type where one could specify both indexes.

In general, though, agreed.  Also, lower bounds should be inclusive,
upper bounds exclusive.  (Thus, for an array with -5...5 as bounds,
the legal indexes should be -5...4.  But the number of elements is
always upper_bounds - lower_bounds.)

|> 4. Containers should store and return values, not references.
|> (If the user wants to store and return values that happen to be pointers,
|> fine. Then the user is responsible for creating and deleting the objects
|> pointed to.)

Better yet, there should be two versions.  One should store and return
values.  Of course, in this case, the stored values are *not*
polymorphic.  The other should guarentee polymorphic values, but may
only handle classes that define a 'clone' function.  From an external
viewpoint, it should also implement value semantics, but with full
support for polymorphism.  Thus:

 BaseClass*  pb = array[ index ].clone() ;

would result in pb pointing to a class of the correct type.


|> 5. Be able to turn off assertion checking in time-critical sections. A botched
|> assertion should call "abort" rather than throwing an exception.

A basic library class should *never* throw an exception.  Generally
speaking, I would favor call-back functions.  The default would abort.
But the user should be able to override the default.  If the user
routine returns, the result should be some reasonable behavior (which
may be extremely difficult to define).  Any exception should be thrown
by the user routine.  (The exception handling strategy must be part of
the application, not of the library.)
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung




Author: kanze@us-es.sel.de (James Kanze)
Date: 19 May 93 19:08:55
Raw View
In article <C77004.8oJ@megatest.com> djones@megatest.com (Dave Jones)
writes:

|> From article <1t88na$elp@cville-srv.wam.umd.edu>, by krc@wam.umd.edu (Kevin R. Coombes):
|> > In article <9313704.15852@mulga.cs.mu.OZ.AU> fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
|> ))maxtal@physics.su.OZ.AU (John Max Skaller) writes:
|> ))
|> ))) What do *you* all want from the library?
|> ))
|> ))I would like a string class, a template fixed length array class (just like C
|> ))arrays, except they have optional bounds checking), and a template dynamic
|> ))array class (size is dynamically allocated at construction but thereafter
|> ))remains fixed). A very simple template list class might also be good.
|> ))If they're going to do a list class then they might as well do stack
|> ))and queue classes, it's hardly any more work.
|> ))And a map (associative array) class would be nice.
|> ))
|> ))These should all be concrete classes, I don't think there's any need
|> ))for any virtual functions.
|> ))
|> )
|> ) I almost agree. The strings, arrays, and lists should be concrete.
|> ) But there are times when I want a stack (or queue) to be implemented
|> ) as a list, and there are other times when I want it implemented as an
|> ) array. Are you sure there shouldn't be virtual functions?
|> )

|> I agree with Fergus.

|> How often do you need to keep a collection of stacks, some of which
|> are implemented one way, some in another? It is only when the implementation
|> type of the stack can not be known until runtime that virtual functions
|> are needed. I can't remember ever needing that functionality. Templates
|> decide the question at compile time.

I disagree.  You seem to be creating a false dicotomy: run-time vs.
compile-time.  The optimal implementation of a stack will depend on
application dependant data, ie: how many elements will it contain,
etc.  I would like to experiment, with most of my functions totally
unaware of the stack implementation.  The implementation will only be
decided in the module where I define the actual variable.

Of course, it would be possible to write *all* of my functions that
access the stack(s) as templates.  But this requires a fair amount of
design to avoid code bloat, making sure that all of the parts of the
function which don't depend on the implementation of a stack are in
separate (non-template) functions.  I would much rather just code in
function of Stack, and not worry how it is implemented.
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Tue, 25 May 1993 03:49:28 GMT
Raw View
jimad@microsoft.com (Jim Adcock) writes:

>fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>|C++ has serious problems trying to support moveable objects, since
>|in C++ the address of an object is its identity.  (Note the lack of a
>|'renew' in C++.)
>
>I disagree both that C++ has serious problems trying to support moveable
>objects, and that the address of an object is its identity.
>
>Regards the first issue, A C++ implementation that moves objects ...

What I meant when I said the above was that C++ *programs* will have
difficulties if they try to move arbitrary objects around.  This is
because you never know whether the object has stored a pointer to it's
own storage somewhere.

I did not mean to imply that C++ *implementations* can't move objects
around, indeed as you correctly note, they already do this (at the OS
level).

>In regards to whether or not addresses in C++ correspond to object
>identities, below find a simple counterexample:
[...]
>  printf("pab != pac -- in C++ addresses DO NOT correspond to"
>   " object identity\n");

You example doesn't sufficiently justify it's conclusion, IMHO.
Since the pointers point to different subobjects, I would expect
them to compare unequal.

--
Fergus Henderson                     This .signature virus might be
fjh@munta.cs.mu.OZ.AU                getting old, but you still can't
                                     consistently believe it unless you
Linux: Choice of a GNU Generation    copy it to your own .signature file!




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Tue, 25 May 1993 03:52:56 GMT
Raw View
swf@tools3teradata.com (Stan Friesen) writes:

>Just because something *acts* like a pointer or reference does not mean
>that it actually *is* one.
>
>There is no *necessity* to make the internal memory pointers accessible,
>even with my sugegsted syntax.  The operator[] does *not* have to return
>an actual reference, it can return a 'wrapper' class.

But this doesn't work very well, because of C++'s lack of support for
smart references. As I noted earlier, returning a wrapper prevents
both of the following:
 array[index]++;
 array[index].member_func();

--
Fergus Henderson                     This .signature virus might be
fjh@munta.cs.mu.OZ.AU                getting old, but you still can't
                                     consistently believe it unless you
Linux: Choice of a GNU Generation    copy it to your own .signature file!




Author: rigby@patty.gud.siemens.co.at (***ANDi RiGBY***)
Date: Wed, 26 May 1993 14:08:18 GMT
Raw View
We're doing a project where we've specified that our
source code will be XPG3 compatible. We are also using
the standard components from USL and was wondering if
*they* are actually to this standard. I get strange compiling
errors with String.h when I try and compile with
-D_XOPEN_SOURCE (or whatever its called) flag it doesn't
work & I need to include -D_STDC_ to make it work.

Thanx in advance,
ANDi RiGBY
(please could you mail me cos recently our newsreader has
been down quite a bit)
(rigby@patty.gud.siemens.co.at)




Author: swf@tools3teradata.com (Stan Friesen)
Date: 20 May 93 15:54:36 GMT
Raw View
In article <C7Avuw.4Ev@megatest.com>, djones@megatest.com (Dave Jones) writes:
|> ... If an object stores values, then
|> addresses of internal memory that exists only because the stored values
|> are not of a bounded size should not be made visible to the client.

And with a 'smart pointer' they do not need to be.  You do not, or should
not, normally extract the 'real' pointer, you stay with the encapsulated
*accessor*, an accessor that happens to *behave* like a pointer (in terms
of the operations supported), but is *implemented* in a way appropriate
to the container it is providing access to.

The reason I prefer this is that it allows the container classes to be used
in a way that is seemlessly integrated with the built-in container (the
native array).  That is, one can use a single loop paradigm for all
containers.

|> |> [my discussion of the inefficiency of copy-modify-copy deleted].
|> I have no problem with that. I just don't want the mechanism for making
|> that efficient modification to be a pointer into internal memory, or
|> even something that "mimics" a pointer.

It would only mimic the pointer in the same way as a 'next value' function
does, it would provide an *access* route to the data inside of the container.

The main values of the 'smart-pointer' type of iterator are efficiency
and uniformity of paradigm with the C containers.

|> For example, consider what we call a "map" or "dictionary". The abstract
|> value it holds is a set of ordered pairs, no two of which have the same
|> first term. Let us assume that we want to change the value, but only slightly,
|> We want all pairs to remain the same except for one. The map holds
|> the pair {key1,value1}, and we want it to hold {key1, value2} instead.
|> A member function "rebind" does the trick:
|>
|>  void Map::rebind(Key key, Value value);
|>  // ...
|>  map.rebind(key1, value2);

I prefer:
 map[key1] = value2;

I view a map as an associative array, I want it to act like one.

Note that operator[] need not return a reference, it could return a 'private'
accessor class with its operator= defined as, essentially, your map::rebind().

|> That member function lets the internal memory allocation "leak out".
|> I think any library function that lets such references "out of the bag"
|> is under an obligation not to rearrange its internal representation, because
|> its internal representation is not intirely hidden. ...

This is not necessarily true.  The internal representation can still be
hidden, it just requires intermediate accessor classes to be used.


Really, I feel that the whole should be integrated into a single paradigm,
and since C has already provided one, and that one is unchangeable, we
need to use it.

--
sarima@teradata.com   (formerly tdatirv!sarima)
  or
Stanley.Friesen@ElSegundoCA.ncr.com




Author: Eric.Price@FtCollins.NCR.com (Eric.Price)
Date: 20 May 93 11:46:25 GMT
Raw View
We have found Standard Components (the USL library of "standard
components") extermely beneficial.

So, for purposes of providing some specificity to the discussion of
"what should be in a library", here's what's in USL's.

FEATURES

General Purpose - reusable for applications and other library routines
providing real cost savings in development and test time and maintenance
costs.

Designed for efficiency - small standalone non-hierarchical components
provide for greater compile and run time efficiency.

Designed by AT&T Bell Laboratories to work with the standard for C++ -
provides assurance of library efficiency with USL's C++ Release 2.0 and
Release 2.1, upon which leading C++ suppliers base their compilers.

Tested and reliable - over 2 years of production use, in a wide range of
applications, within AT&T Bell Laboratories, lowers the risk of use in
critical applications.

PRODUCT COMPONENTS

Included in the C++ Standard Components are the following components:

Args - a set of facilities providing more natural and convenient access to
UNIX System command line options and arguments than typical command line
parsers.

Bits - extends built-in support for bit manipulation to arbitrary-length
bitstrings.  It also allows easy access to individual bits and provides
additional operations such as concatenation.

Blocks  - are like built-in arrays, except that their size can be adjusted
dynamically.  Using Blocks eliminates many of the errors programmers make
structures.

Block Algorithms - 90 highly efficient algorithms for operating on
contiguously stored data (can be used with either arrest or Blocks) including
algorithms for searching, sorting, inserting, partitioning, generation,
copying, and removing.

Fsm - offers a method of specifying program control flow that is useful in a
wide variety of applications.  Programmers define states and transitions among
states that are fired by specific inputs.

Graphs - three classes that can be used to maintain arbitrary relationships
between arbitrary entities.  Useful for semantic modeling and other network
applications.

Graph Algorithms - Several of the most fundamental algorithms for operating on
Graphs, including breadth-first and depth-first searching, cycle and component
detection.

Ipcstream - specializes the standard I/O architecture (iostream) to
interprocess communication between clients and servers.  Clients and servers
communicate by writing to or reading from streams.

Lists - are doubly-linked lists.  Since pointer manipulation and node
allocation are handled automatically, using Lists eliminates another major
source of programming errors.

Maps - are like arrays, except that the subscripts can be non-integral types
such as character string (similar to associative arrays in AWK).

Objections -  an error object that can be raised by one piece of code and
handled by another  (like UNIX software signals).

Path - a set of facilities for manipulating UNIX path names and UNIX search
paths.  Includes automatic canonicalization, relativization, wildcard and
tilde expansion, completion, and searching.

Pools - improve the runtime performance of programs which allocate and
deallocate many objects of the same type (for example, Lists use Pools
internally for obtaining nodes).

Regex - a set of facilities providing a consistent and enhanced interface to
the Section 3 regular expression compilation and matching routines.

Sets - three unordered homogeneous collection classes: Sets, Bags, and pointer
sets.  Provides the usual insertion, removal, membership algebraic and
relational operators and iterators.

Stopwatch - can be used for timing critical sections of code during the
performance tuning phase of development.

Strings - are variable-length character strings.  Strings offer an efficient
alternative to null-terminated character arrays and their associated C library
functions (strcpy, strcmp, etc).

Strstream - specialize the standard I/O architecture (iostream) to in-core
formatting, where the source or target is a String.

Symbol - unique identifiers based on character strings with efficient tests
for equality and ordering.

Time - consists of three related abstractions for dealing with time in
computer programs:   Time (absolute time), Duration (time difference) and
Place (geographical location).

--
Eric Price, Software Architect, Computer Aided Design
NCR Microelectronic Products Division
2001 Danfield Court; Ft. Collins, CO 80525
(303) 223-5100 x9471; FAX: 226-9556; EMAIL: Eric.Price@FtCollinsCO.NCR.COM




Author: decker@cs.sunysb.edu (David V. Ecker)
Date: 21 May 1993 03:31:27 GMT
Raw View
I am looking for some good UNIX, C, and C++ books.
That will make me a wizard not a stupid programmer like I am now. :-)

If you know of any please e-mail me( decker@sbcs.sunysb.edu)

Thanks for your help,
DAvid.





Author: edwards@kong.gsfc.nasa.gov (Stephen G. Edwards)
Date: 21 May 1993 14:05:35 GMT
Raw View
In article <1993May20.170016.9834@ucc.su.OZ.AU>, maxtal@physics.su.OZ.AU
(John Max Skaller) wrote:
>
> In article <1993May19.213014.23398@massey.ac.nz> MStern@massey.ac.nz (M.W. Stern) writes:
> >maxtal@physics.su.OZ.AU (John Max Skaller) writes:
> >
> >>       What do *you* all want from the library?
> >
> >In respect to container classes I think a look at the container classes
> >provided by Borland's BID classes is worth while. Although I haven't used
> >these classes they seem to be pretty comprehensive.
> >
> >They allow containers to store either objects or references to objects. The
> >former you may use to store objects that will only ever appear in one
> >container. The latter to store objects that will be grouped in many different
> >containers. The container library should also handle ownership, and control
> >over who destrys the objects.
>
>  Actually, I think this is probably not the best way, though
> I'm by no means sure. I suspect that a container owns the objects
> in it, full stop.
>
>  But owning a pointer doesnt mean anything, it doesnt mean
> owning the object pointed to.
>
>  Does anyone have opinion on this: is it wise to
> have dynamic control over object ownership in containers?

In my experience, no.  It's just too confusing.  Programmers like to know
what an object is doing just by knowing its identity, rather than having to
investigate how it's being used.  But neither is one approach suitable for
all situations.  So on our latest project, we yielded to the inevitable and
defined, for example, two versions of a simple list:

   PtrList - holds pointers, does not own the object pointed to
   DeepList - holds pointers, but DOES own the object pointed to

Copying or destroying a DeepList will also copy and destroy its contents,
respectively.  A PtrList just copies or throws away its pointers.

Redundant?  Sure, but so what.  At least we've eliminated perceived memory
management ambiguities.  And our programmers have started using a style
whereby objects have a permanent home in a DeepList, but may have temporary
residences in a number of PtrLists, which has really helped us keep the
number of memory leaks/illegal accesses down.

---
Stephen G. Edwards                       email: edwards@kong.gsfc.nasa.gov
NASA Goddard Space Flight Center         phone: (301) 286-6676
Code 522.2                                 fax: (301) 286-4627
Greenbelt, MD 20771




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Fri, 21 May 1993 15:58:15 GMT
Raw View
In article <edwards-210593095041@sedwards.gsfc.nasa.gov> edwards@kong.gsfc.nasa.gov (Stephen G. Edwards) writes:
>>
>>  Does anyone have opinion on this: is it wise to
>> have dynamic control over object ownership in containers?
>
>In my experience, no.  It's just too confusing.  Programmers like to know
>what an object is doing just by knowing its identity, rather than having to
>investigate how it's being used.  But neither is one approach suitable for
>all situations.  So on our latest project, we yielded to the inevitable and
>defined, for example, two versions of a simple list:
>
>   PtrList - holds pointers, does not own the object pointed to
>   DeepList - holds pointers, but DOES own the object pointed to
>
>Copying or destroying a DeepList will also copy and destroy its contents,
>respectively.  A PtrList just copies or throws away its pointers.
>
>Redundant?  Sure, but so what.  At least we've eliminated perceived memory
>management ambiguities.  And our programmers have started using a style
>whereby objects have a permanent home in a DeepList, but may have temporary
>residences in a number of PtrLists, which has really helped us keep the
>number of memory leaks/illegal accesses down.
>

 Another **BIG** advantage of this: the DeepList can
have pointers to a low level base class (like 'Object' :-)
because it need be used only for storage management.

 But the other PtrList's can be subsets of the DeepList,
and might hold particular derived types.

 That means that instead of using downcasting on the DeepList
to extract type information, you just run through the PtrList
that is for that type: no downcasting, much faster.

 Do you do this?

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: Stephen G. Edwards <edwards@kong.gsfc.nasa.gov>
Date: 21 May 1993 17:35:36 GMT
Raw View
In article <1993May21.155815.15321@ucc.su.OZ.AU> John Max Skaller,
maxtal@physics.su.OZ.AU writes:
>In article <edwards-210593095041@sedwards.gsfc.nasa.gov>
>edwards@kong.gsfc.nasa.gov (Stephen G. Edwards) writes:
>>>
>>>  Does anyone have opinion on this: is it wise to
>>> have dynamic control over object ownership in containers?

[...]

>>   PtrList - holds pointers, does not own the object pointed to
>>   DeepList - holds pointers, but DOES own the object pointed to
>>
>>Copying or destroying a DeepList will also copy and destroy its contents,
>>respectively.  A PtrList just copies or throws away its pointers.
>>

[...]

>
> Another **BIG** advantage of this: the DeepList can
>have pointers to a low level base class (like 'Object' :-)
>because it need be used only for storage management.
>
> But the other PtrList's can be subsets of the DeepList,
>and might hold particular derived types.
>
> That means that instead of using downcasting on the DeepList
>to extract type information, you just run through the PtrList
>that is for that type: no downcasting, much faster.
>
> Do you do this?

Kind of.  I know of one component that maintains a group of objects in a
DeepList, and then uses several PtrLists to categorize those objects.  Because
these lists are built at startup and not modified during execution, it's an
efficient way to allow fetching of all the objects in a particular category --
just return the right PtrList.

I never really thought of using it in the way you suggest, but it looks like a
promising technique.

On a side note, I should also emphasize that PtrList and DeepList are class
templates, lest anyone think we're doing any nasty unnecessary downcasting.

---
Stephen G. Edwards                     email: edwards@kong.gsfc.nasa.gov
Code 522.2                             phone: (301) 286-6676
NASA/Goddard Space Flight Center         fax: (301) 286-4627
Greenbelt, MD  20771




Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 19 May 93 02:02:00 GMT
Raw View

johnsone@camax.com (Eric Johnson @ CAMAX Systems, Inc.) writes

 > 1. Name-space protection. All class and type names should have some
 > standard prefix to prevent name-space conflicts with component software
 > (e.g., X Window System, Motif, etc.). The one that first comes to mind
 > is that very nasty X data type "String". Now, I don't like the fact that
 > the X folks decided to take over String for all time. I just ask that
 > ANSI doesn't follow suit. Let's learn from the mistake. More and more
 > software developers are using software components in our products,
 > so name-space collisions are becoming more and more of a problem.

This is top of the extensions working group's priority list. The proposal
on the table looks like this:

 namespace X {
  class String { ... }; // library X's string
  // ...
 }

 namespace Y {
  class String { ... }; // library y's string
  // ...
 }

 void f()
 {
  X::String s = "asdf"; // using X's string
  // ...
 }

 void g()
 {
  using Y::String; // String refers to Y::String
     // in this scope

  String s = "asdf"; // using Y's string
  // ...
 }

I hope to see this accepted at the July meeting (in Munich) and have
some reason to hope that will happen. There is a longish discussion of
the proposal in the latest ANSI/ISO mailing so people who are interested
enough to do some work should contact their ANSI or ISO rep. People who
are just curious can look at a brief description in next month's issue
of the C++ Report.

 > 2. We market our software worldwide. I suspect a number of other
 > companies do as well. Hence, an ANSI C++ string class should allow
 > for internationalized text. Using multibyte text may be the easiest
 > (since you can still use char*) although I still hope something
 > like Unicode will be adopted worldwide. In any case, member functions
 > on a string class to get a particular character, to compare two
 > strings, to get the string length (in characters insteda of bytes--
 > although both functions will be needed), numeric, date and time
 > formatting, etc., will need to be internationalized.

A String class that can cope with extended character sets is being
considerd, and so are the modifications to iostreams to deal with
initernationalization issues.

 - Bjarne




Author: djones@megatest.com (Dave Jones)
Date: Sat, 22 May 1993 01:37:37 GMT
Raw View
In article <edwards-210593095041@sedwards.gsfc.nasa.gov> edwards@kong.gsfc.nasa.gov (Stephen G. Edwards) writes:
>>
>>  Does anyone have opinion on this: is it wise to
>> have dynamic control over object ownership in containers?
>
>In my experience, no.  It's just too confusing.  Programmers like to know
>what an object is doing just by knowing its identity, rather than having to
>investigate how it's being used.  But neither is one approach suitable for
>all situations.  So on our latest project, we yielded to the inevitable and
>defined, for example, two versions of a simple list:
>
>   PtrList - holds pointers, does not own the object pointed to
>   DeepList - holds pointers, but DOES own the object pointed to

All you need (and definitely all *I want*) is a list that holds values of an
arbitrary type:

 template<class Item>
 class List;

If you want to use a list that "holds pointers, does not own the object
pointed to," the user declares it to hold pointers (naturally):

 class Rec;
 List<Rec *> list;

If you want to use a list that "holds pointers, but DOES own the object
pointed to," well, let me suggest that what your *really* want is
a class that manages the pointer. The reason you want a deep copy is that
the thing pointed to is effectively a *value*, so codify the value semantics:

 class Value {
 private:
       Rec *pointer;
 public:
       Value() pointer(0) {;}
       Value(const Value &vin) { /* "deep" copy */ }
       Value& operator= (const Value &vin) { /* ditto */ }
       ~Value() { delete pointer; }
 };

 List<Value> val_list;

When you remove a Value from the list, the destructor will take care
of deleting it.




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Sat, 22 May 1993 13:16:16 GMT
Raw View
swf@tools3teradata.com (Stan Friesen) writes:

>djones@megatest.com (Dave Jones) writes:
>|>  map.rebind(key1, value2);
>
>I prefer:
> map[key1] = value2;
>
>I view a map as an associative array, I want it to act like one.
>
>Note that operator[] need not return a reference, it could return a 'private'
>accessor class with its operator= defined as, essentially, your map::rebind().

The difficulty with that is that I can't do
 Map<Key, int> map;
 map[key1]++;
or
 Map<Key, List<String> > map;
 map[key1].insert("foo");

(if operator dot was overloadable then that would solve the second case)

>|> That member function lets the internal memory allocation "leak out".
>|> I think any library function that lets such references "out of the bag"
>|> is under an obligation not to rearrange its internal representation, because
>|> its internal representation is not intirely hidden. ...
>
>This is not necessarily true.  The internal representation can still be
>hidden, it just requires intermediate accessor classes to be used.

C++ has serious problems trying to support moveable objects, since
in C++ the address of an object is its identity.  (Note the lack of a
'renew' in C++.)
What this should mean, at least in theory, is that template collection
classes must never move objects around. And in that case, there's
no danger in letting a reference or pointer to an object in the collection
escape.

However, in practice, I think there is a better way of resolving things:
in the documentation for your collection class, document that it
only supports moveable objects, and document that references returned
by operator[] are only guaranteed to be valid until the next call
of any collection member function (even a const member function).
Then, if the user hangs on to a reference for too long, it's *their fault*.
Achieving perfect safety for your class users is not always worthwhile.

--
Fergus Henderson                     This .signature virus might be
fjh@munta.cs.mu.OZ.AU                getting old, but you still can't
                                     consistently believe it unless you
Linux: Choice of a GNU Generation    copy it to your own .signature file!




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Sat, 22 May 1993 13:37:30 GMT
Raw View
edwards@kong.gsfc.nasa.gov (Stephen G. Edwards) writes:

>maxtal@physics.su.OZ.AU (John Max Skaller) wrote:
>>
>>  Does anyone have opinion on this: is it wise to
>> have dynamic control over object ownership in containers?
>
>In my experience, no.  It's just too confusing.  Programmers like to know
>what an object is doing just by knowing its identity, rather than having to
>investigate how it's being used.  But neither is one approach suitable for
>all situations.  So on our latest project, we yielded to the inevitable and
>defined, for example, two versions of a simple list:
>
>   PtrList - holds pointers, does not own the object pointed to
>   DeepList - holds pointers, but DOES own the object pointed to
>
>Copying or destroying a DeepList will also copy and destroy its contents,
>respectively.  A PtrList just copies or throws away its pointers.
>
>Redundant?  Sure, but so what.  At least we've eliminated perceived memory
>management ambiguities.

No, I don't consider this redundant.
In fact there is another possibility as well: you might want to use
reference counting to decide when to destroy things.
But there is a nice way of implementing these possibilities:
define two smart pointer classes
 DeepPtr<T> // a deep pointer to T
 RefCntPtr<T> // a reference counted pointer to T
and then PtrList<T> can be defined using List<T *>, DeepList<T> can
be defined using List< DeepPtr<T> >, and RefCntList<T> can be defined
using List< RefCntPtr<T> >. (A pity there's no such thing as a template
typedef!)

Of course, you might want to define DeepList<T> and RefCntList<T> in
terms of List <DeepPtr<void *> > and List <RefCntPtr<void *> >
respectively, to avoid unnecessary code duplication.

--
Fergus Henderson                     This .signature virus might be
fjh@munta.cs.mu.OZ.AU                getting old, but you still can't
                                     consistently believe it unless you
Linux: Choice of a GNU Generation    copy it to your own .signature file!




Author: grumpy@cbnewse.cb.att.com (Paul J Lucas)
Date: Sat, 22 May 1993 17:15:52 GMT
Raw View


Author: Geir.Halbo@idt.unit.no (Geir Halbo)
Date: 23 May 93 04:56:50
Raw View
In article <9314223.28075@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:

   The difficulty with that is that I can't do
    Map<Key, int> map;
    map[key1]++;
   or
    Map<Key, List<String> > map;
    map[key1].insert("foo");

On the discussion of "leaking" internal memory: I really think you
gurus defining standards would do a big, counter-OO mistake if you
made the above impossible, i.e., make it impossible to invoke object
operations (member funcs) on an object instance which is a member
of a collection.

This would be sacrificing a very useful feature for the sake of an
abstract principle, opposite the philosophy underlying C.


While I have your attention, let me mention that the USL library of
standard components described by Eric Price seems to contain a lot of
*very* useful stuff without being overloaded (!), such as Args, FSMs,
Graphs, IPC, Pools etc.

 - geir

--
MSc Geir Halbo     !  Department of Computer Systems and Telematics (IDT)
Halbo@idt.unit.no  !  Norwegian Institute of Technology             (NTH)
+ 47 7 59 36 74    !  University of Trondheim                      (UNIT)
/G=Geir/S=Halbo/OU=IDT/O=Unit/C=No/PRMD=Uninett




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sun, 23 May 1993 15:46:46 GMT
Raw View
In article <C7FuMH.67G@cbnewse.cb.att.com> grumpy@cbnewse.cb.att.com (Paul J Lucas) writes:
>From article <25516@alice.att.com>, by bs@alice.att.com (Bjarne Stroustrup):
>>
>> johnsone@camax.com (Eric Johnson @ CAMAX Systems, Inc.) writes
>>
>>  > 1. Name-space protection.
>
>> This is top of the extensions working group's priority list. The proposal
>> on the table looks like this:
>>
>>  namespace X {
>>   class String { ... }; // library X's string
>>   // ...
>>  }
>>
>>  namespace Y {
>>   class String { ... }; // library y's string
>>   // ...
>>  }
>>
>>  void g()
>>  {
>>   using Y::String; // String refers to Y::String
>>      // in this scope
>>
>>   String s = "asdf"; // using Y's string
>>   // ...
>>  }
>
> I think that...
>
>  void g() {
>   using Y::String {
>    String s = "asdf"; // using Y's string
>    // ...
>   }
>  }
>
> ...is perhaps an improvement (?) because it reinforces the scope
> of String.

 But you can do that, just swap the using and brackets around:

  void g() {
   { using Y::String
    String s = "asdf"; // using Y's string
    // ...
   }
  }


> redo the last example like this...
>
>  void h2() {
>   using Y::String;
>
>   String s = "asdf"; // using Y's string
>   // ...
>
>   using X::String; // change what String means
>
>   String s = "ghjk"; // using X's string
>   // ...
>  }
>
 Nope, cant do that. The using is more or less
equivalent to

 typedef Y::String String;

so the above is a duplicate definition.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: grumpy@cbnewse.cb.att.com (Paul J Lucas)
Date: Sun, 23 May 1993 19:45:37 GMT
Raw View


Author: djones@megatest.com (Dave Jones)
Date: Sun, 23 May 1993 22:20:52 GMT
Raw View


Author: tmb@arolla.idiap.ch (Thomas M. Breuel)
Date: 24 May 93 04:21:45
Raw View
>>>>> On Sun, 23 May 1993 22:20:52 GMT, djones@megatest.com (Dave Jones) said:
> I would prefer not to have container classes that let the internal memory
> pointers leak out and then invalidate them, even if they are documented not
> to be valid after the next time the container is accessed. I think that
> is asking for trouble.

That is a general problem with C++: "internal memory pointers" can
"leak out" all over the place in C++ programs.

The solution you propose, making internal addresses of data structure
not be lvalues is not necessarily very effective, but it is quite
cumbersome.  In particular, passing a location by reference is a
frequent and safe operation, as is assigning to some internal
location.

I think a better solution than to simply avoid exposing all lvalues is
not to use the address-of operator.  With reference types, the need to
do so has been greatly diminished.  And, if you forsake use of the
address-of operator, you are safe from unintentionally keeping
pointers not only to the guts of your own data structures, but also to
the guts of third party data structures, old-style C data structures,
and even automatic variables.

In fact, I think Ellis and Detlefs in their "safe subset" proposal
forbid most uses of the address-of operator in safe code and have the
compiler make sure of it.

     Thomas.




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Mon, 24 May 1993 07:57:42 GMT
Raw View
In article <C7Hw83.1xx@cbnewse.cb.att.com> grumpy@cbnewse.cb.att.com (Paul J Lucas) writes:

[Namespaces]

>>The using is more or less
>> equivalent to
>>
>>  typedef Y::String String;
>
> Is there any reason why the above typedef can't be used instead
> of introducing the "using" keyword?  This makes more sense and
> seems more orthogonal to me.

 typedef doesnt work too well with functions.

 using math::sine;
 using mymath::cosine;

this uses whole overloaded families of functions: sine(float)
and sine(complex) get used because they have one name.

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: krc@wam.umd.edu (Kevin R. Coombes)
Date: 17 May 1993 14:50:18 GMT
Raw View
In article <9313704.15852@mulga.cs.mu.OZ.AU> fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
>maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>
>> What do *you* all want from the library?
>
>I would like a string class, a template fixed length array class (just like C
>arrays, except they have optional bounds checking), and a template dynamic
>array class (size is dynamically allocated at construction but thereafter
>remains fixed). A very simple template list class might also be good.
>If they're going to do a list class then they might as well do stack
>and queue classes, it's hardly any more work.
>And a map (associative array) class would be nice.
>
>These should all be concrete classes, I don't think there's any need
>for any virtual functions.
>

I almost agree. The strings, arrays, and lists should be concrete.
But there are times when I want a stack (or queue) to be implemented
as a list, and there are other times when I want it implemented as an
array. Are you sure there shouldn't be virtual functions?

Kevin Coombes <krc@math.umd.edu>




Author: swf@tools3teradata.com (Stan Friesen)
Date: 17 May 93 15:37:22 GMT
Raw View
In article <1993May16.095058.12107@ucc.su.OZ.AU>, maxtal@physics.su.OZ.AU (John Max Skaller) writes:
|> >
|> >Of course, I would also like to have a standard set of container classes,
|> >but apparently they are not considering that problem.
|>
|>  Yes, they are considering containers. There may be a
|> class DynArray for extensible arrays, for example.
|>
|>  What do *you* all want from the library?

A *full* set of container classes: sets, bags, stacks, lists, queues, trees,
rings associative arrays (?maps), perhaps even bi-associative arrays.

And make sure each of them has an associated iterator class.
[I prefer iterators based on the 'pointer' model - dereference to access
the value, increment operator to go th the 'next' item].

[Perhaps you could use the tools.h++ set of container classes as your basis?]

--
sarima@teradata.com   (formerly tdatirv!sarima)
  or
Stanley.Friesen@ElSegundoCA.ncr.com




Author: djones@megatest.com (Dave Jones)
Date: Mon, 17 May 1993 22:18:28 GMT
Raw View


Author: djones@megatest.com (Dave Jones)
Date: Mon, 17 May 1993 22:32:55 GMT
Raw View


Author: nectar@world.std.com (Nectar Nirvana)
Date: Tue, 18 May 1993 03:30:16 GMT
Raw View
djones@megatest.com (Dave Jones) writes:

[deleted some wants for standard class libs]

>I think I want the following properties. (I'm sure someone will tell
>me where I am wrong.)

>0. Skinnny interfaces. Classes should be unintrusive. They
>should not require that the objects they manipulate be derived from a
>single do-everything base class. Which brings us to...

Amen!  Yes!  Yeah!

[deleted other wishes]
--
Nectar Nirvana --><--  | "The absurd is the essential concept
nectar@world.std.com  |  and the first truth." - A. Camus




Author: djones@megatest.com (Dave Jones)
Date: Tue, 18 May 1993 01:00:29 GMT
Raw View


Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Tue, 18 May 1993 14:30:55 GMT
Raw View
In article <1t88na$elp@cville-srv.wam.umd.edu> krc@wam.umd.edu (Kevin R. Coombes) writes:
>In article <9313704.15852@mulga.cs.mu.OZ.AU> fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
>>maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>>
>>> What do *you* all want from the library?
>>
>>I would like a string class, a template fixed length array class (just like C
>>arrays, except they have optional bounds checking), and a template dynamic
>>array class (size is dynamically allocated at construction but thereafter
>>remains fixed). A very simple template list class might also be good.
>>If they're going to do a list class then they might as well do stack
>>and queue classes, it's hardly any more work.
>>And a map (associative array) class would be nice.
>>
>>These should all be concrete classes, I don't think there's any need
>>for any virtual functions.
>>
>
>I almost agree. The strings, arrays, and lists should be concrete.
>But there are times when I want a stack (or queue) to be implemented
>as a list, and there are other times when I want it implemented as an
>array. Are you sure there shouldn't be virtual functions?
>

 Well, I've thrown an abstract array and an abstract
extensible array at the net before.

 Now its my turn. HELP!

 Will someone please post a brief sketch of a list class
to the net (or email me?).

 Note: I mean a *list* not an array, that is, something
you can perform 'list surgery' on. Perhaps this class
will be represented as an iterator. Dont know. A generic
abstract class is probably the go, as well as perhaps one
concrete instance. Again, dont know.

 As far as I know, there is no proposal yet before the
committee for these things. (There is for string and dynarray).

 How about smart pointers?

 Well, nows your chance, but dont be tardy .. there's a two
week deadline looming :-(


--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: johnsone@camax.com (Eric Johnson)
Date: Tue, 18 May 1993 16:19:19 GMT
Raw View
swf@tools3teradata.com (Stan Friesen) writes:

>In article <1993May16.095058.12107@ucc.su.OZ.AU>, maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>|> >
>|> >Of course, I would also like to have a standard set of container classes,
>|> >but apparently they are not considering that problem.
>|>
>|>  Yes, they are considering containers. There may be a
>|> class DynArray for extensible arrays, for example.
>|>
>|>  What do *you* all want from the library?

>A *full* set of container classes: sets, bags, stacks, lists, queues, trees,
>rings associative arrays (?maps), perhaps even bi-associative arrays.

>And make sure each of them has an associated iterator class.
>[I prefer iterators based on the 'pointer' model - dereference to access
>the value, increment operator to go th the 'next' item].
>--
>sarima@teradata.com   (formerly tdatirv!sarima)
>  or
>Stanley.Friesen@ElSegundoCA.ncr.com

Just to add to this:

1. Name-space protection. All class and type names should have some
standard prefix to prevent name-space conflicts with component software
(e.g., X Window System, Motif, etc.). The one that first comes to mind
is that very nasty X data type "String". Now, I don't like the fact that
the X folks decided to take over String for all time. I just ask that
ANSI doesn't follow suit. Let's learn from the mistake. More and more
software developers are using software components in our products,
so name-space collisions are becoming more and more of a problem.

2. We market our software worldwide. I suspect a number of other
companies do as well. Hence, an ANSI C++ string class should allow
for internationalized text. Using multibyte text may be the easiest
(since you can still use char*) although I still hope something
like Unicode will be adopted worldwide. In any case, member functions
on a string class to get a particular character, to compare two
strings, to get the string length (in characters insteda of bytes--
although both functions will be needed), numeric, date and time
formatting, etc., will need to be internationalized.

Just my $0.02,
-Eric

--
Swallow a slug             Eric F. Johnson           email: johnsone@camax.com
By its tail or its snout   CAMAX Systems, Inc.       phone: +1 612 854 5300
Feel it slide down         7851 Metro Parkway        fax:   +1 612 854 6644
Feel it climb out          Minneapolis, MN 55425 USA




Author: jbn@lulea.trab.se (Johan Bengtsson)
Date: 18 May 93 18:31:23 GMT
Raw View
Dave Jones (djones@megatest.com) wrote:

: A botched
: assertion should call "abort" rather than throwing an exception.

Not everyone would agree.  Having failed assertions throw exceptions
is certainly a valid and safe approach.  Many programs can't afford to
just die:

- A professional application should tell the user that "menu choice XYZ
  suffers from a programming error, please notify your supplier", or
  something similar.

- Important server processes may wish to just log such programming errors,
  and continue, assuming the bug will have limited impact on other clients.

I agree that in many other cases it is preferable to make the programming
error as apparent as possible.  There is also the small twist that
exception handling code should not use assertions that may throw exceptions,
to avoid not-so-fun infinite recursion.

Since there is a choice, I believe the assertion checking system
should allow the user to choose between the abort() and exception
behaviour.

--
-------------------------------------------------------------------------
| Johan Bengtsson, Telia Research AB, Aurorum 6, S-977 75 Lulea, Sweden |
| Johan.Bengtsson@lulea.trab.se; Voice:(+46)92075471; Fax:(+46)92075490 |
-------------------------------------------------------------------------




Author: djones@megatest.com (Dave Jones)
Date: Tue, 18 May 1993 21:10:31 GMT
Raw View


Author: swf@tools3teradata.com (Stan Friesen)
Date: 18 May 93 16:35:21 GMT
Raw View
In article <C776u3.9A9@megatest.com>, djones@megatest.com (Dave Jones) writes:
|>
|> But I would prefer that most container classes be designed to store and
|> return values, not to offer memory that is externally accessible. ...

You misunderstood what I was trying to say.
I did not say the iterator should return a raw pointer, I said it
should *mimic* a pointer.

That is the iterator class should take the form of a smart pointer.
|>
|>  HashTable map;
|>
|>  addSomeAssociations(map);
|>
|>  HashIter iter(map);
|>  for(;iter;iter++) {
|>     *iter = newValue(); // Generally bad idea, I think.
|>         }

This is not quite what I meant, I meant something closer to:

 HashTable map;

 addSomeAssociations(map);

 for(HashIter iter = map; iter; iter++)
 {
  ... iter->hash_member() ... // use iter as if it were a pointer
 }
[Although your treatment would be a useful way to do a copy-in of a
value from somewhere else].

|>
|> ... but the canonical return value from operator* is a reference. I don't
|> think container classes should return references to their internal objects,
|> and I think that operator* should work as expected. Therefore, I think I
|> prefer a "next" function that returns a value.

I am not sure what you mean here.  A 'value' return is a *copy* - this makes
it impossible to modify an item in a container, except possibly by using a
copy-out/modify/copy-in sequence (via an assignment operator).  This seems
extremely inefficient, especially compared to native arrays.

I would really insist on the ability to modify a contained object in place,
especially via member function of the contained object.

--
sarima@teradata.com   (formerly tdatirv!sarima)
  or
Stanley.Friesen@ElSegundoCA.ncr.com




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Wed, 19 May 1993 08:47:45 GMT
Raw View
In article <1993May18.161919.3306@camax.com> johnsone@camax.com (Eric Johnson) writes:
>swf@tools3teradata.com (Stan Friesen) writes:
>
>>In article <1993May16.095058.12107@ucc.su.OZ.AU>, maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>>|> >
>>|> >Of course, I would also like to have a standard set of container classes,
>>|> >but apparently they are not considering that problem.
>>|>
>>|>  Yes, they are considering containers. There may be a
>>|> class DynArray for extensible arrays, for example.
>>|>
>>|>  What do *you* all want from the library?
>
>>A *full* set of container classes: sets, bags, stacks, lists, queues, trees,
>>rings associative arrays (?maps), perhaps even bi-associative arrays.
>
>>And make sure each of them has an associated iterator class.
>>[I prefer iterators based on the 'pointer' model - dereference to access
>>the value, increment operator to go th the 'next' item].
>>--
>>sarima@teradata.com   (formerly tdatirv!sarima)
>>  or
>>Stanley.Friesen@ElSegundoCA.ncr.com
>
>Just to add to this:
>
>1. Name-space protection. All class and type names should have some
>standard prefix to prevent name-space conflicts with component software
>(e.g., X Window System, Motif, etc.).

 Not necessary. There will (probably) be a complete
namespace control mechanism added to the C++ language to solve
this problem. You wont need silly prefixes,

 ISO_String

you can  have instead

 ISO::String

and say

 using ISO::String;
 String s;

>The one that first comes to mind
>is that very nasty X data type "String". Now, I don't like the fact that
>the X folks decided to take over String for all time. I just ask that
>ANSI doesn't follow suit. Let's learn from the mistake. More and more
>software developers are using software components in our products,
>so name-space collisions are becoming more and more of a problem.

 Which is why the complete solution of a namespace
mechanism is being considered, and will probably be accepted (IMHO).
>
>2. We market our software worldwide. I suspect a number of other
>companies do as well. Hence, an ANSI C++ string class should allow
>for internationalized text.

 Right. Right with you on this.

>Using multibyte text may be the easiest
>(since you can still use char*) although I still hope something
>like Unicode will be adopted worldwide. In any case, member functions
>on a string class to get a particular character, to compare two
>strings, to get the string length (in characters insteda of bytes--
>although both functions will be needed), numeric, date and time
>formatting, etc., will need to be internationalized.
>

 Getting this right is non-trival. I am leaning
towards a class 'text' which is a string of 'wchar_t'.
Object oriented class, handles big files. Separate
'string' class for utility operations with 'char' which will
be concrete class.

Comments? Anyone reading this know anything about internationalisation
issues and character sets?

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Wed, 19 May 1993 09:30:28 GMT
Raw View
In article <C78qv2.H2H@megatest.com> djones@megatest.com (Dave Jones) writes:
>From article <1993May18.143055.20917@ucc.su.OZ.AU), by maxtal@physics.su.OZ.AU (John Max Skaller):
>...
>)  Now its my turn. HELP!
>)
>)  Will someone please post a brief sketch of a list class
>) to the net (or email me?).
>)
>)  Note: I mean a *list* not an array, that is, something
>) you can perform 'list surgery' on.
>
>Can you be more specific? Do you mean "list" and in singly/doubly linked list?
>What is list surgery?

 List surgery: the ability to cut and paste lists from place
to place, for example, attach a list to the end of another list,
*without copying*.

 Whats not a list class? A class that enables you to say

 1) get first element
 2) get next element after that one

is not a list class: its an array class. If you can get the first
element, and then get the next element, then you can clearly
get the 'n'th element: exactly as for an array.

 A real list might be represented by an iterator
that
 a) cannot be copied
 b) can be incremented to point to the next element

the idea being that you can only ever access *one* element,
and once you've finished with it, it is completely
inaccessible.

 Perhaps array and list insertion are different:
inserting into an array may or may not imply copying,
inserting into a list guarrantees not to copy things.

 OK, I'm clearly waffling here :-)
I'd like someone to describe exactly what an abstract list
is (assume singly linked .. doubly linked lists are not
important or particularly interesting : they have to
be either linear or circular. But single linked lists
can form trees :-)

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: sjm@bnr.ca (Stuart MacMartin)
Date: Wed, 19 May 1993 13:38:17 GMT
Raw View
In article <C76zC2.8L0@megatest.com> djones@megatest.com (Dave Jones) writes:
>Oh. Well, I'm not completely sure, but I could get by initially with just the
>basics: lists, queues, maps, graphs, et cetera. And oh yeah, regular
>expressions.
It's amazing what you can do with simple, well designed, data structures.
Or how you can abuse them.  Fancy structures are often not used when linked
lists of linked lists will do.  Many programmers do not go through a list
of available data structures and say, "Which is the best"?  Rather, they
say, "Will my tried and true one do the job?"  Thus it is important that:

1.  Interfaces be clean
2.  It is easy to chain them together (lists of lists)
3.  How to use them is well documented
4.  *When* to use them is well documented (or they won't get the use
    they deserve).

>0. Skinnny interfaces. Classes should be unintrusive. They
>should not require that the objects they manipulate be derived from a
>single do-everything base class. Which brings us to...

This may sound obvious, but putting an object of class A into a particular
collection should not affect the implementation of class A.  (This is not
true of some collections provided for C).

>2. Keep implementation details out of the "signature" of classes.
>
>       GOOD
>
> template<class Key, class Value>
> Map {
> const int default_size = 32;
> public: Map(int initial_size = default_size);
> //...
> };
>
>       NOT SO GOOD
>
> template<class Key, class Value, int Size>
> Map {
> public: Map();
> //...
> };

YES!!! PLEASE!!!  But I'll go farther: The "GOOD" example is bad
because the implementation requires tinkering that should not be
necessary.  The biggest abuser of this always seems to be hash
tables.  If I am using a hash table, I do not want to be making the
trade-off between table size and overflow size, and I do not want to
be actively involved in any resizing.  The programmer using a hash
table may know that sometimes there are 20 entries and sometimes
there are 20,000.  What is s/he to do?  And all he wants is to use
a hash table because that's the best way to do it.  He doesn't want
to be tinkering with it!

The hash table should use extendible hashing with an *unconstrained*
hash function, and the table should extend as needed to use the next
(appropriate) bit of the hash function.  I do this, and it works
beautifully.  The hash table is efficient and does not abuse memory
when it is very small and when it is very big.  The unconstrained
hash value of each entry can be checked in the overflow buckets, so
this algorithm makes overflow buckets of 50 elements practical,
which reduces the size of the hash table itself.

Other people may want other implementations of hash functions.
If so, there should be several options available.  But the one I
want is an off-the-shelf one-size-fits-all hash table.

>3. For operator[], indexes always start at zero.
If operator[] is defined for some collections, it should be defined
for all collections.  I would like a standard collection interface.
I would then be able to easily change the collection class I am using.
It might seem natural to have a base collection class...

**** BUT ****
We will often have tens or hundreds of thousands of *small* collections.
We do not want much overhead on these, either space or construction/
destruction time.  There has to be a collection class that will work
for this case but still allow me to use at least a minimal standard
interface.

>4. Containers should store and return values, not references.
>(If the user wants to store and return values that happen to be pointers,
>fine. Then the user is responsible for creating and deleting the objects
>pointed to.)

We have two usual cases:

1.  We are storing small structures, like a pair of points, in one place.
    This is best done by value:  if we had to store pointers, we would
    have a lot of space and time overhead.

2.  Often we have larger structures (currently our code is in C) that
    are stored in several collections.  These collections store pointers.

If the way the lists will be used in case 2 is impacted by having the
lists store values, then I want two kinds of lists: those that store
values, and those that store pointers.

>5. Be able to turn off assertion checking in time-critical sections. A botched
>assertion should call "abort" rather than throwing an exception.

Agreed.  I would like to be able to:

1.  Re-compile to turn on debugging information.
    (I don't want all those error messages and assertion checks to
    take up module space.)

2.  Use an environment variable to turn on some simpler debugging.
    If I can turn on object self-test at various points (like when
    an object is added to or removed from a list) then I can find
    some errors without resorting to a general debugger.

I also need to be able to create my own collections and match the
standard collection interface.  I need to store intervals and
rectangles efficiently and with efficient response to queries;
I need to add things like divided K-D trees.

Stuart
--
== Stuart MacMartin   sjm@bnr.ca   Bell-Northern Research, Ottawa, CANADA
==                                 Standard disclaimers apply




Author: MStern@massey.ac.nz (M.W. Stern)
Date: Wed, 19 May 93 21:30:14 GMT
Raw View
maxtal@physics.su.OZ.AU (John Max Skaller) writes:

>       What do *you* all want from the library?

In respect to container classes I think a look at the container classes
provided by Borland's BID classes is worth while. Although I haven't used
these classes they seem to be pretty comprehensive.

They allow containers to store either objects or references to objects. The
former you may use to store objects that will only ever appear in one
container. The latter to store objects that will be grouped in many different
containers. The container library should also handle ownership, and control
over who destrys the objects.

They allow easy swapping between different structures to implement the
same contruction thus allowing a program to be optimised for speed or
memory requirements. For example, a queue could be implemented using a
single linked list, or a double linked list, or using a block of memory
directly (vector structure).

In a standard library I would require the above functionality as in past
work (using Borland Pascal) I have used it.




Author: jimad@microsoft.com (Jim Adcock)
Date: 19 May 93 16:45:33 GMT
Raw View
In article <C76zC2.8L0@megatest.com> djones@megatest.com (Dave Jones) writes:
|I think I want the following properties. (I'm sure someone will tell
|me where I am wrong.)

I don't see how anyone can tell you whether you are right or whether
you are wrong, without you explaining to us your rationale, instead
of just telling us your opinions.  IF C++ is going to have some
standard classes, its going to be because a wide agreement has been
formed about how and *why* some standard classes should be written.
Failing that, there is no basis for having a *standard* class library.

Also, ideally a standard class specification is chosen to allow some
variation in implementation.  The specification should call out a standard
interface, *not* a standard implementation.  Thus, interfaces that dictate
a particular implementation are probably too low level.  IE requiring
a pointer to be the iter element is probably too low level a specification.
Having a specification that calls out SOME type of iter element, details
of actual type of that iter element unspecified might be preferred.

Also note that traditionally standard libraries have been willing to
sacrifice something in the way of ease of use for more abstraction,
allowing a wider variation of implementation of the classes on the
widest variety of machines.  If you were to call out a spec of a class
that couldn't be equally efficiently implemented on all machines,
then that would argue strongly against your design choices.  Again,
I encourage you to think of relatively abstract interface specifications
on the classes you propose, and to avoid specifying implementation.
If you can't think of three different and widely varying ways to
implement the classes whose interfaces you are specifying, then you
interface spec is certainly too low level.




Author: djones@megatest.com (Dave Jones)
Date: Thu, 20 May 1993 00:53:44 GMT
Raw View
Oops. I accidently posted the following to the wrong thread. If you've seen it
already, well, sorry about that.



swf@tools3teradata.com (Stan Friesen) writes:
> djones@megatest.com (Dave Jones) writes:
>>>
>>> But I would prefer that most container classes be designed to store and
>>> return values, not to offer memory that is externally accessible. ...
>
> You misunderstood what I was trying to say.
> I did not say the iterator should return a raw pointer, I said it
> should *mimic* a pointer.

Try to bear with me here...

I try to make the distinction between abstract values and (computer)
objects. An abstract value is something that is assumed to exist in
some mathematical model. For example, there is the number three. (Why does
this sound like Sesame Street?) It does not exist in the computer. In
fact it does not exist at all in the concrete sense. We conventionally
choose computer bit patterns to designate these abstract values.

When we need to model concrete, real world objects, we formulate
theories of abstract values using composites of mathematical
abstract values. For example, we might abstract the notion of a coin-changer
machine as a listing of attributes such as the weights of various kinds of
coins "known" to it, the currency value of the coins, a count of how
many of each kind of coin is currently stored, etc.

So far so good.

In order to automate reasoning about a real-world object, perhaps for the
purpose of controling it automatically, we allocate computer memory
corresponding to the object and the real world objects it interacts with.
This allocation would be very straight-forward if every type of value in our
abstract models could be stored in a bounded amount of computer memory.
But some computer objects are by their nature unbounded in size, for
example, an object for containing a list of integers may need arbitrary
amounts of computer memory. The code for maintaining that object
(the list-container) must be capable of allocating new memory as needed.

I want my library classes to be very explicit about whether they are
mechanisms for storing values, or are mechanisms for allocating memory
(objects) that the library client may manipulate independently. If they
provide memory, that memory should be stable and accessible for the
lifetime of the memory-providing object. If an object stores values, then
addresses of internal memory that exists only because the stored values
are not of a bounded size should not be made visible to the client.

> [...]
> I am not sure what you mean here.  A 'value' return is a *copy* - this makes
> it impossible to modify an item in a container, except possibly by using a
> copy-out/modify/copy-in sequence (via an assignment operator).  This seems
> extremely inefficient, especially compared to native arrays.
>
> I would really insist on the ability to modify a contained object in place,
> especially via member function of the contained object.

I have no problem with that. I just don't want the mechanism for making
that efficient modification to be a pointer into internal memory, or
even something that "mimics" a pointer.

For example, consider what we call a "map" or "dictionary". The abstract
value it holds is a set of ordered pairs, no two of which have the same
first term. Let us assume that we want to change the value, but only slightly,
We want all pairs to remain the same except for one. The map holds
the pair {key1,value1}, and we want it to hold {key1, value2} instead.
A member function "rebind" does the trick:

 void Map::rebind(Key key, Value value);
 // ...
 map.rebind(key1, value2);

The map now has the new, slightly different, value. The rebind function
could be parameterized by "const Key &key", et cetera. In C++ that is
idomatic for "a quick peek" when passing the value itself might
be inefficient. I am gradually coming to accept that idiom, if somewhat
reluctantly. But I still don't care for the following:

 Value& Map::lookup();
 // ...
 *map.lookup(key1) = value2;

That member function lets the internal memory allocation "leak out".
I think any library function that lets such references "out of the bag"
is under an obligation not to rearrange its internal representation, because
its internal representation is not intirely hidden. The object is, in effect,
a memory-provider rather than a value-storer.




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Thu, 20 May 1993 06:21:46 GMT
Raw View
maxtal@physics.su.OZ.AU (John Max Skaller) writes:

>djones@megatest.com (Dave Jones) writes:
>>maxtal@physics.su.OZ.AU (John Max Skaller):
>>...
>>)  Will someone please post a brief sketch of a list class
>>) to the net (or email me?).
>>)
>>)  Note: I mean a *list* not an array, that is, something
>>) you can perform 'list surgery' on.
>>
>>Can you be more specific? Do you mean "list" and in singly/doubly linked list?
>>What is list surgery?
>
> List surgery: the ability to cut and paste lists from place
>to place, for example, attach a list to the end of another list,
>*without copying*.

The problem with lists of this sort is memory management.
If a list node can be on more than one list, who is responsible
for deleting the node?
GC would solve this. Reference counting can almost solve this,
but it doesn't work for circular lists (and it's not particularly
efficient anyway).

--
Fergus Henderson                     This .signature virus might be
fjh@munta.cs.mu.OZ.AU                getting old, but you still can't
                                     consistently believe it unless you
Linux: Choice of a GNU Generation    copy it to your own .signature file!




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Thu, 20 May 1993 17:00:16 GMT
Raw View
In article <1993May19.213014.23398@massey.ac.nz> MStern@massey.ac.nz (M.W. Stern) writes:
>maxtal@physics.su.OZ.AU (John Max Skaller) writes:
>
>>       What do *you* all want from the library?
>
>In respect to container classes I think a look at the container classes
>provided by Borland's BID classes is worth while. Although I haven't used
>these classes they seem to be pretty comprehensive.
>
>They allow containers to store either objects or references to objects. The
>former you may use to store objects that will only ever appear in one
>container. The latter to store objects that will be grouped in many different
>containers. The container library should also handle ownership, and control
>over who destrys the objects.

 Actually, I think this is probably not the best way, though
I'm by no means sure. I suspect that a container owns the objects
in it, full stop.

 But owning a pointer doesnt mean anything, it doesnt mean
owning the object pointed to.

 Does anyone have opinion on this: is it wise to
have dynamic control over object ownership in containers?

--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: djones@megatest.com (Dave Jones)
Date: Thu, 13 May 1993 02:48:25 GMT
Raw View
Is there work underway to standardize a container class library?
How about Strings?

If so, who's in on it, and what has been proposed so far?

 Thanks,
 Dave




Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Fri, 14 May 1993 17:24:46 GMT
Raw View
In article <C6y2I0.Fpr@megatest.com> djones@megatest.com (Dave Jones) writes:
>Is there work underway to standardize a container class library?
>How about Strings?
>
>If so, who's in on it, and what has been proposed so far?
>

 There is a string class.

 The members of X3J16 and WG21 are in on the plot.

 What do you want?


--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: djones@megatest.com (Dave Jones)
Date: Sun, 16 May 1993 01:44:14 GMT
Raw View


Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sun, 16 May 1993 09:50:58 GMT
Raw View
In article <C73JJ0.GHI@megatest.com> djones@megatest.com (Dave Jones) writes:
>From article <1993May14.172446.17635@ucc.su.OZ.AU), by maxtal@physics.su.OZ.AU (John Max Skaller):
>) In article <C6y2I0.Fpr@megatest.com) djones@megatest.com (Dave Jones) writes:
>))Is there work underway to standardize a container class library?
>))How about Strings?
>))
>))If so, who's in on it, and what has been proposed so far?
>))
>)
>)  There is a string class.
>)
>)  The members of X3J16 and WG21 are in on the plot.
>)
>)  What do you want?
>
>
>I want the draft standard for the String class (so I can write a conforming
>shell around an existing String class). Could someone please post it?

 That wasnt quite what I meant. What I meant was what do you want
in a string class? Anyone out there: what do *you* want?

 You wouldn't be well advised I dont think to work with the
draft string class .. its only a draft.
>
>Of course, I would also like to have a standard set of container classes,
>but apparently they are not considering that problem.

 Yes, they are considering containers. There may be a
class DynArray for extensible arrays, for example.

 What do *you* all want from the library?


--
        JOHN (MAX) SKALLER,         INTERNET:maxtal@suphys.physics.su.oz.au
 Maxtal Pty Ltd,      CSERVE:10236.1703
        6 MacKay St ASHFIELD,     Mem: SA IT/9/22,SC22/WG21
        NSW 2131, AUSTRALIA




Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Sun, 16 May 1993 18:24:47 GMT
Raw View
maxtal@physics.su.OZ.AU (John Max Skaller) writes:

> What do *you* all want from the library?

I would like a string class, a template fixed length array class (just like C
arrays, except they have optional bounds checking), and a template dynamic
array class (size is dynamically allocated at construction but thereafter
remains fixed). A very simple template list class might also be good.
If they're going to do a list class then they might as well do stack
and queue classes, it's hardly any more work.
And a map (associative array) class would be nice.

These should all be concrete classes, I don't think there's any need
for any virtual functions.





Author: marc@offline.be (Marc Duponcheel)
Date: 17 May 93 00:17:46 PST
Raw View
In article <9313704.15852@mulga.cs.mu.OZ.AU> fjh@cs.mu.OZ.AU (Fergus Henderson) writes:

> These should all be concrete classes, I don't think there's any need
> for any virtual functions.

Please make them virtual ...

What if someone makes a list with an Insert (at head) and Append (at tail)
and I just want to derive a SortedList. I would like to redefine Insert and
Append to to the same thing (put at sorted place) ...

-- marc.

##########################################################################
  preferred address = marc@offline.be
  e-mail marc@offline.be marc@offline.UUCP offline!marc ub4b!offline!marc
  fido   2:292/603.26 Marc.Duponcheel@p26.f603.n292.z2.FidoNet.Org
  bix    mduponcheel mduponcheel@BIX.com
##########################################################################




Author: jak@cs.brown.edu (Jak Kirman)
Date: Mon, 17 May 1993 02:22:51 GMT
Raw View
In regards to a standard components collection class, the following
comments appeared:

fjh@cs.mu.OZ.AU: I don't think there's any need for any virtual functions.
marc@offline.be: Please make them virtual ...

I imagine the decision about whether to design these standard components
so they are efficient or so they are extensible will be a source of
contention; I don't believe there is a reasonable middle ground for
basic classes implementing things like strings and collections.

Personally I would prefer something along the lines of the Unix System
Labs Standard Components, with the emphasis strongly on efficiency and
simplicity, for several reasons.

1) The efficiency of the building blocks of any system is obviously
critical; a large number of developers will avoid using them unless they
are as efficient as anything else that is readily available.

2) There is too much disagreement about which bells and whistles are
good to get any consensus on which ones should be added to standard
classes.  Bells and whistles sometimes slow down the executables,
usually slow down the compilation, and almost always slow down the
implementors learning to use a package and in maintaining it.

3) Flexible, extensible classes can easily be created on top of efficient
basic components, but not vice versa.  It would be nice to have a
standard for such extensible classes, but I don't think it is reasonable
to expect it to appear before everyone is agreed on the basic components.

So I would argue for a simple, if not minimalistic, set of classes,
designed to be as efficient as possible while allowing them to be used
to implement more sophisticated classes.

There are a number of things I don't like about the USL Standard
Components; their choice of names like "String" and "Set" have caused us
endless problems, but I agree with their philosophy of efficiency above
all, and they are closer to what I would like in a standard than
other packages I have seen (leda, gnu, ET++, NIHCL off the top of my
head).

Personally, I would like to see strings, dynamic arrays, lists and sets.
Maps (associative arrays), and some kind of regular expression would be
nice, but of lower priority (I am not sure how tightly strings and
regular expressions should be integrated).

I have a couple of questions for those on the committees looking at
this:

a) What is the policy concerning efficiency versus flexibility?

b) What naming conventions will you use?  While for a standard library
it would be nice to have simple names like String and List, I am sure
you are aware of the problems this causes.