[comp.lang.c++] Abstract vs. Template classes

stt@inmet (10/18/89)

There are indications that parameterized/template
classes will be added to C++ someday soon.
I think this is too bad, because the concept
of a generalized "abstract" class seems more useful,
and could accomplish the same goal as parameterized
classes without introducing yet another concept.
(An "abstract" class is meant to be any class with some number
of virtual components which have no corresponding default definition,
indicated via "=0" in C++ 2.0 parlance).

Bertrand Meyer makes the point in "Object-oriented
Software Construction" that even multiple inheritance 
is not "enough" as far as he is concerned,
and a separate generic/parameterized class concept is
essential.

I would claim that a way to merge the concepts
of abstract classes and parameterized classes is
simply to allow classes to have "virtual" object components,
"virtual" typedef components, etc.  In other words, allow
a class to have per-class (i.e. "static") 
"virtual" components of any
sort, rather than simply virtual function
components.

The actual definition of these components may be provided/overridden
in any class derived from the original one.
Any reference to these components implies a level of
indirection through the equivalent of the virtual-function table.

Here is a small example, based on the Example
in Lippman's "C++ Primer":

class List {
public:
    virtual typedef PT;  /* was a template parameter */
			       /* detailed syntax TBD */
    List (PT *pt = 0, List *lpt = 0) /* constructor */
	: val(pt), next(lpt) {}
    PT *append(List *);   /* an operation */
private:
    PT *val;              /* instance variables */
    List *next;
};

The intention is that what would have been template parameters
become virtual components of the class.  The "virtual typedef"
would hopefully allow flexibility in defining the nature of the
actual type specified in derived classes.  For instance, it
could specify that the actual type specified be a class derived
from some particular (abstract) base class.  This allows
the remaining code within the class with the virtual typedef
to perform operations on instances of the virtual type
using this knowledge.   Similarly, it should be possible
say something like  "virtual typedef void* PT;" to indicate that
the actual type may be any pointer type.

Another useful kind of parameterization is to allow
"virtual" object components of an (abstract class).  
This would allow different
derivatives of a base class to have distinct class-wide
tables, for example, controlling the action of
the derived class.  Virtual object components would
be similar to static components of a class, except that they
could be overridden in a derived class.

An advantage of this approach over a distinct parameterization
mechanism is that partial instantiation is possible by
overriding some of the virtual object/type components, while
leaving others still undefined.
Furthermore, it is possible to provide default
bindings for the virtual object/type components, allowing
a derived class to only override those it wishes to and use
the defaults for the others.
Finally, it makes it clear that the code is intended to
be shared between distinct derivations/instantiations, whereas
with a template the tendency is to treat them as macros.

S. Tucker Taft     stt%inmet@uunet.uu.net
Intermetrics, Inc.
Cambridge, MA  02138

jima@hplsla.HP.COM (Jim Adcock) (10/20/89)

Hm, I always thought the "whole" idea of the C++ approach, and templates in
particular, was to avoid the additional gratuitous indirections present in
other OOPLs, thus retaining C-like speed.  In which case "template" needs to
be a macro-like implementation, with little capabilities for machine-code reuse.

I would think one could "fake" genericity via "gratuitous-indirection"
relatively trivially by coercing the type of pointer used in derived classes.
And in fact using pointers may be a reasonable approach if what being pointed
to is large.  To get reasonable performance if what is pointed to is small,
you need to use templates to avoid the indirection completely.

jeenglis@girtab.usc.edu (Joe English) (10/21/89)

jima@hplsla.HP.COM (Jim Adcock) writes:
>Hm, I always thought the "whole" idea of the C++ approach, and templates in
>particular, was to avoid the additional gratuitous indirections present in
>other OOPLs, thus retaining C-like speed.  In which case "template" needs to
>be a macro-like implementation, with little capabilities for machine-code reuse.

Why not allow both templates (macroexpanded) and
abstract member functions (compiled once and using
virtual pointers to parameter type operations)?


In the parameterized class, you could define small
functions as inline, medium sized functions that make
lots of references to the class parameters as
templates, and let large functions that make few
parameter references be compiled once and stuck
in a library. The compiler would create a virtual 
function table for parameter operations for every
different instantiation of the parameterized class.

Of course, an implementation could *probably* do
that anyway using the template syntax, if all of
the needed parameter operations were declared:


class OrderedList<class T>
{
    T::operator<();     // T must have the comparison operators;
    T::operator<();     // The addresses of these functions would be placed
    T::operator==();    // in the paramater table of OrderedList instantiations

	OrderedList& insert(T&);	// makes calls thru parameter table
	template OrderedList& delete(T&)	// macroexpanded
	// ... etc.
};


>I would think one could "fake" genericity via "gratuitous-indirection"
>relatively trivially by coercing the type of pointer used in derived classes.

Yes, but one of the reasons for wanting parameterized classes
in the first place is to make this kind of code rewriting
unnecessary.

By the way, how long before parameterization is fully supported?
What will it look like?

--Joe English

  jeenglis@nunki.usc.edu