From: shang@corp.mot.com (David (Lujun) Shang)
Subject: Polymorphic Arguments -- An Informal Proposal
Reply-To: shang@corp.mot.com
Organization: Motorola, Inc., Software Research and Development, Rolling Meadows, IL. 60008
Date: Wed, 12 Aug 92 20:10:36 GMT


The following proposal is informal and incomplete. It is proposed for 
the purpose to give some hints to solve some major problems in the 
current C++. I have not enough spare time to make a complete 
investagation, if someone is interested or happened to have the 
similiar thought, please let me know.

A constant, variable, parameter, reference, or pointer can be 
polymorphic. We call them polymorphic arguments.

A polymorphic argument specified by class C can represent an 
object of class C or one of its derived classes.

We call a non-polymorphic argument a type exact argument. A type 
exact argument can accept an object of a derived class with a 
conversion (slicing) to its exactly specified type.

In the present C++, a constant, a vriable, or a parameter is 
a type exact argument. A class pointer or class reference is 
a polymorphic argument.

In extended C++, we will have polymorphic constant, variable, 
and parameter:

   poly Animal a;
   const poly Animal a,  // usually as a function parameter

and we will have type exact pointer and reference:

   Animal sealed * ap;
   Animal sealed * af;

Type exact pointer or reference cannot accept a value of pointer 
or reference of derived classes. For example, "ap=aMammalPointer" 
is invalid, and slicing will be made for "*ap =aMammal".

We should distinguish a polymorphic pointer from a pointer to a 
polymorphic argument:

   poly Animal * ap;

is a pointer to a polymorphic argument, but pointer itself is not 
polymorphic. However,

   Animal * ap; // it is "Animal poly * p" by default

is a polymorphic pointer but the argument pointed by the pointer 
is not polymorphic.

Why should we distinguish a polymorphic argument from a exact 
argument? Let us first consider the general implementation issues:

(1) For a polymorphic argument, we need combine a type reference 
with the object code.

(2) For a type exact argument, only object code is presented. 

Therefore, we can 

(1) Integrate the convensional C types into class hierarchy 
without sacrifying the space and the speed, since convensional 
C arguments are not polymorphic, and we need not to combine a 
type reference with them. For example, if we treat "int" as a 
class,

   int i;

is still 4 byte (for 32bit machine) long.

(2) Implement a complete RTTI without the overhead on space if you 
do not use them. The type code is included into the run time code 
only when you use it with a polymorphic argument. For example, the 
type code for "int" class is included into run time code (at link 
time), only when you write the following code:

   poly number np;
   ...
   np = anInteger;

Therefore, each type or class has a type code but not necessarily 
to be included into run time type code if you do not use it with 
polymorphism.

(3) Implement sizeof(), typeof() of a polymorphic argument correctly. 
Since each type will have a code, we can include two standard fields 
in the type code, one is the unique (project-wide) type identifier 
(can be an integer), the other is the real size of the object code. 
(Here we can take the advantage of the fact that the type code is 
linked into the run time code only for those types associated with  
polymorphism.)

(4) Implement increment and decrement of pointers correctly (the 
same reason as we can implement a correct sizeof()).

(5) Save the storage for homogeneous object container. For example,

    Animal * p;
    Dog da[1000];
    Cat ca[20000];

In current C++, if Animal has virtual functions, "da" will have 
additional 4K bytes and "ca" will waste 80K bytes! It is really 
not necessary to tag all objects in a homogeneous object container 
since they are all in the same type. Now, since we only tag those 
polymorphic arguments, we need only tag the polymorphic pointer p. 
When

   p = da;

"p" get both the address of the "da" and the type of "Dog". 
(When p++, p increases by the actual size of a dog.)

In case of one pointer vs. many heterogeneous objects, we 
can use a polymorphic pointer to refer to many specific 
non-polymorphic objects. Therefore, we can save much space.

In case of many pointers vs. one polymorphic object, we can 
use non-polymorphic pointers to the polymorphic object. This 
is the same struture in the current C++ implementation.

David Shang


Newsgroups: comp.lang.c++