[comp.lang.c++] About Lists and things ... Mostly requests for info.

djones@megatest.UUCP (Dave Jones) (06/17/91)

Hello,

First a couple of requests:

1. I would appreciate it if someone would send me the article titled
"How to define a List class (summary)".

2. I've only recently re-subscribed to this group, and I fear I've missed
quite a bit. Where can I find out about the plans for language extensions
such as parameterized types, templates, catch-and-throw, et cetera? I've
just bought a stack of back-issues of _C++ Report_ and some other literature,
but there is little there on these topics. Perhaps there is a conference coming
up soon? I'm in the mood for a boondoggle.

Concerning (1)... For the last six years or so I've been doing the following in C,


        extern void* List_iter_next(); /* actually declared
                                        * in an include-file of course
                                        */

        run_through(my_list)
           List *my_list; /* Linked list of SomeType (pointers) */
        {
           List_iter iter;
           SomeType *member;

           List_iter_init(&iter, my_list);

           while( member = (SomeType*)List_iter_next(&iter)) {

		... fiddle with *member

           }

        }


C++ophiles will notice that in the vernacular of C++, List_iter_init() is a
constructor for the class List_iter, and that the parameter &iter is the
this-pointer. (No destructor is needed.) List_iter_next() is a member-function
of the class List_iter. Of course, "List" has its complement of member-functions
also, some "in-lined" with macros. (I wrote a whole libary that way before I ever
heard of C++.)

Anyway, the above works pretty well, except that I get millions of complaints from
lint about the type-conversions from void*, and a new compiler I've been using
complains about the "assignment inside a conditional". So far, I haven't been
able to think up a much better solution in C++ because there's still the problem of
casting the void* back to SomeType*. Perhaps parameterized types will
save the day, but using #defines to generate do-nothing type-conversion
routines does not seem like any improvement on the above. My principle value-metric
for this is fewest key-strokes, not elegance, not type-security. I'm guessing
that the "How to Define a List class (summary)" paper will show me the True Way.
What is the popular wisdom?

chip@tct.com (Chip Salzenberg) (06/19/91)

According to djones@megatest.UUCP (Dave Jones):
> while( member = (SomeType*)List_iter_next(&iter))

Aargh.

This is exactly the downcast hackery that I avoid at all costs.  I
don't mind using pointers without seatbelts, but with my object types
I want a four-point harness and an airbag.
-- 
Chip Salzenberg at Teltronics/TCT     <chip@tct.com>, <uunet!pdn!tct!chip>
 "You can call Usenet a democracy if you want to.  You can call it a
  totalitarian dictatorship run by space aliens and the ghost of Elvis.
  It doesn't matter either way."  -- Dave Mack

djones@megatest.UUCP (Dave Jones) (06/20/91)

From article <285E75EC.37E7@tct.com>, by chip@tct.com (Chip Salzenberg):
> According to djones@megatest.UUCP (Dave Jones):
>> while( member = (SomeType*)List_iter_next(&iter))
> 
> Aargh.
> 
> This is exactly the downcast hackery that I avoid at all costs.

And that is exactly the kind of derisive pedantry that I avoid at all
costs.

Even though the above technique has proved perfectly adequate in C-code
for six years, my posting asked for a better way to do it in C++.
Do you have any suggestions, or only insults?

thomasw@hpcupt1.cup.hp.com (Thomas Wang) (06/22/91)

>From article <285E75EC.37E7@tct.com>, by chip@tct.com (Chip Salzenberg):
>> According to djones@megatest.UUCP (Dave Jones):
>>> while( member = (SomeType*)List_iter_next(&iter))
>>
>> Aargh.
>>
>> This is exactly the downcast hackery that I avoid at all costs.

>And that is exactly the kind of derisive pedantry that I avoid at all
>costs.

>Even though the above technique has proved perfectly adequate in C-code
>for six years, my posting asked for a better way to do it in C++.
>Do you have any suggestions, or only insults?

Basically there are two camps.  One camp think in order to have a list that
can contain anything, type cast down facility must be provided.  Another
camp think type cast down is dangerous, and one should use templates
instead.

Although using templates is type safe.  It restricts the things that can be
inside the list to one type only.  Some people say this is too restrictive.
People counters with :"What is the last time you want more than one type
of objects inside a list?"

In order to have safe type down cast, three things must be provided.
(1) Mechanism to determine if it is safe to do the down cast.
(2) Mechanism to perform the down cast.
(3) Exception handling mechanism to handle type casting error.

Currently C++ does not explicitly support the three mechanisms.  Programmers
must roll their own thing.  How this can be accomplished is disscussed here
many times, so I will not repeat it.  The solutions proposed all have some
aspect of kluge associated with them.


I personally think program re-use without type down cast is difficult.
I hope that safe type down cast can be implemented in a future version
of C++ compiler.

 -Thomas Wang
              (GC is the key to everything.)
                                                     wang@hpdmsjlm.cup.hp.com
                                                     thomasw@hpcupt1.cup.hp.com

nagle@well.sf.ca.us (John Nagle) (06/24/91)

    It's frustrating.  C++ has classes but not generics.  Ada has generics
but not classes.  Pascal and Modula (I and II) have neither.
The languages that have both tend to have too much other excess baggage
at run time.

    Another level of preprocessor is not the answer.  (Some C++ implementations
now have three preprocessors; template to C++, C++ to C, and standard C 
preprocessing.)  Generics as part of the language seem the right approach.
It's straightforward to determine when the generic is instantiated if the
same code used for another instantiation can be reused.  You get full
type safety and no extra run-time overhead either in space or time.
So this seems the approach of choice.

    Resolving multiple instantiations in separate complilations is
possible at link time if name mangling for generic parameterized types
results in the type of the formal, rather than the actual, type parameter
being used in the mangled name in circumstances where code reuse is possible.
So if you have two copies of the "list" routines because the list class
was instantiated twice in different files, they will result in routines with
the same name and the duplicate can be dropped at link time.

    What's the current proposal from the standards people?

						John Nagle