Topic: The concept of templates considered ill designed


Author: sjm@bcrki65.bnr.ca (Stuart MacMartin)
Date: 13 Oct 92 14:31:29 GMT
Raw View
In article <1992Oct11.133704.5600@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>In article <Eep9xSi00Vp_4391Iw@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:
>>
>>Every advance in languages has been associated with an increased overhead:
>>from assembler to C, from C to C++: every time you switch to a higher level
>>language you lose some speed.
>>
>
> Not true!
(Many examples provided)

Some additional points:

1.  I have seen assembler code that was written because the routine was
    expected to be time critical.  The code looked good on the surface, but
    saved all registers at the start and restored them all at the end.  This
    used up so much time that an equivalent routine I wrote in FORTRAN ran
    20% faster without even using any optimization options on the compiler.

2.  RISC processors exacerbate this problem of writing efficient code.  It
    really is true that the compiler may know how to handle most programming
    constructs better than you do.

3.  Advances in languages allow us to use more appropriate data structures
    and algorithms for the same amount of development time.  For this reason,
    the program written in the higher level language using those advances in
    languages is sometimes orders of magnitude faster than the one written in
    the lower level language.

4.  Sometimes speed is not as much an issue as being able to write the functionality
    in the first place.

Stuart
--
: Stuart MacMartin                                    email: sjm@bnr.ca      :
: Bell-Northern Research                              phone: (613) 763-5625  :
: PO Box 3511, Stn C, Ottawa, K1Y-4H7, CANADA    Standard disclaimers apply. :




Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Fri, 16 Oct 1992 13:03:32 GMT
Raw View
In article <1992Oct15.070015.29776@jyu.fi> sakkinen@jyu.fi (Markku Sakkinen) writes:
>In article <1992Oct13.143129.20733@bcrka451.bnr.ca> sjm@bcrki65.bnr.ca (Stuart MacMartin) writes:
>> [Almost all of a good posting deleted]
>> ...
>>4.  Sometimes speed is not as much an issue as being able to write the functionality
>>    in the first place.
>
>This should be submitted to the Usenet "Understatement of the Month"
>contest :-)
>

 It was.

>----------------------------------------------------------------------
>Markku Sakkinen (sakkinen@jytko.jyu.fi)
>       SAKKINEN@FINJYU.bitnet (alternative network address)
>Department of Computer Science and Information Systems
>University of Jyvaskyla (a's with umlauts)
>PL 35
>SF-40351 Jyvaskyla (umlauts again)
>Finland
>----------------------------------------------------------------------


--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: frank@Cookie.secapl.com (Frank Adams)
Date: Mon, 05 Oct 1992 17:26:02 GMT
Raw View
In article <BvM0DE.EA7@watcgl.uwaterloo.ca> pfbertra@watcgl.uwaterloo.ca (Philippe F. Bertrand) writes:
>In article <1992Oct2.153826.12051@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>It would be nice if templates could have some sort of base class derivation
>rules.  Ie instead of < class T > have <class Foo T> which restricts T to be
>a class publicly derived from Foo.

If something like this is adopted, I think a better syntax would be:

<class T : Foo>

similar to the notation for inheritance.  It would be nice to permit:

<class T : Foo, Bar, int>

meaning class T could be a subclass of Foo or of Bar, or could be type int.
Unfortunately, it is difficult to tell this comma from one introducing a new
parameter.




Author: shang@corp.mot.com (David (Lujun) Shang)
Date: Tue, 6 Oct 92 00:29:28 GMT
Raw View
In article <1992Oct2.153826.12051@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John
MAX Skaller) writes:
>
>  How would you modify the template idea to be better?
>

Constrain class parameters. That's the way I can see to make the template
idea better. For example:

   class Group < class MemberType >
   // unconstrained class parameter MemberType here is equivalent
   // to MemberTyep[anyclass]
   { public:
       virtual void accept ( MemberType m);
   };

   class AnimalGroup: public Group < class MemberType[Animal] >
   {  public:
        virtual void accept ( MemberType m)
        // Here the input interface of member function accept
        // is implicitly narrowed to a type of Animal
        {  Group::accept(m);
           // do something special on Animal here...
        };
   };

   class MammalGroup: public AnimalGroup < class MemberType[Mammal] >
   {  public:
        virtual void accept ( MemberType m)
        // Here the input interface of member function accept
        // is implicitly narrowed to a type of Mammal
        {  AnimalGroup::accept(m);
           // do something special on Mammal here...
        };
   };

   class BearGroup: public MammalGroup < class MemberType=Bear >
   {  public:
        virtual void accept ( MemberType m)
        // Here the input interface of member function accept
        // is implicitly narrowed and FIXED to Bear
        {  MammalGroup::accept(m);
           // do something special on Bear here...
        };
   };

or, simply,

   typedef MammalGroup <class MemberType=Bear> BearGroup;


> >Template is not a self-enclosed type-safe language feature, i.e. it cannot
> >be compiled separately to ensure type-error free. All type errors about the
> >class parameters are checked when the template is used. When the
> >library-developers ship their products, they cannot ensure their templates
> >are type-error free.
>
>  This is not true, of course they can. What you mean
> is that the compiler doesn't help very much, and I agree.
> But I'm sure one could prove that a template was error free
> by hand ( I agree this is not formal system like a compiler check,
> but lets not get into whether a proof actually proves what it purports
> to or not: the usual solution to this problem is to publish the
> proof ).
>

What do you think false in my statement? I'm confused. Temaplate is safe
at run time, no doubt. But it is not a self enclosed type-safe entity.
What I mean is that template is not type-safe for separate compilation.
However, it is type-safe after linking. It is not the fault of the
compiler or any implementation of the templates. The fault lies in
template itself: its parameterized interface is not "typed" or
"constrained".

> >The library user will get confused when an error is reported on the source
code
> >of the template: "should it be my fault or the fault of the template
itself?"




Author: osoelgaultier+@CMU.EDU (Stefan Monnier)
Date: 5 Oct 92 10:58:55 GMT
Raw View
Excerpts from netnews.comp.lang.c++: 5-Oct-92 Re: The concept of
template.. Andrew Koenig@alice.att. (582)

> In article <0enxJ1W00awTMNepU8@andrew.cmu.edu>, osoelgaultier+@CMU.EDU
> (Stefan Monnier) writes:

> > As are currently implemented templates, you don't know
> > anything about the actual type at compile-time.
> > So that no method calls or variable accesses can be compiled
> > for any variable of 'template type'.

> But you still haven't answered my question.

> My question was: what reason do you have to believe that
> adding inheritance constraints would solve the problem?

> In thinking about the answer, don't forget about inline functions.
> --
>     --Andrew Koenig
>       ark@europa.att.com


With inheritance constraints, you can restrict method calls
to those known to be present (through inheritance).
Inlining doesn't make it impossible: it's just harder, cause
you can't keep the compiled version in pure object code, but
you have to keep information on where are the 'parameters' used
in order to translate their use !

What I say is just that inheritance constraint permits to check
the file and compile it before using it !

Maybe inlining is harder to implement, but I personnally don't
care (I don't think it's important, and anyway, it is feasible)

One problem is with 'base' types (int, ...) as they don't inherit.
But I think it's not 'unovercomable' (what a great word, I'll have
to suggest it for introduction in the Harrap's)

 Stefan

-----------------------------------------------------
-- On the average, people seem to be acting normal --
-----------------------------------------------------




Author: shang@corp.mot.com (David (Lujun) Shang)
Date: Tue, 6 Oct 92 00:38:21 GMT
Raw View
In article <TMB.92Oct3050715@arolla.idiap.ch> tmb@arolla.idiap.ch (Thomas M.
Breuel) writes:
> In article <1992Oct2.144959.18480@cadsun.corp.mot.com> shang@corp.mot.com
(David (Lujun) Shang) writes:
>
>    In article <1992Oct1.140643.9775@cadsun.corp.mot.com> shang@corp.mot.com I
>    wrote:
>    Template is not a self-enclosed type-safe language feature, i.e. it cannot
be
>    compiled separately to ensure type-error free. All type errors about the
>    class parameters are checked when the template is used.
>
> Yes. However, the reason for this is not intrinsic in the template
> concept, but in the way templates were "integrated" with overloading
> in C++.
>
>      Thomas.

Could you explain your argument in more detail? As far as I can see,
the reason for this is the intrinsic in the template concept: class
parameters are not constrained. Are there any conflicts between the
concept of constrained parameterized class and the concept of C++
overloading?

David Shang






Author: shang@corp.mot.com (David (Lujun) Shang)
Date: Tue, 6 Oct 92 00:55:50 GMT
Raw View
In article <23796@alice.att.com> ark@alice.att.com (Andrew Koenig) writes:
> In article <BvM0DE.EA7@watcgl.uwaterloo.ca> pfbertra@watcgl.uwaterloo.ca
(Philippe F. Bertrand) writes:
>
> > Also for code hiding, compilers should generate intermediate files for
> > templated code so that user's of a template class do not need to have
> > access to the source.
>
> This is primarily an implementation issue, not alnaugae issue.
> If enough people want compilers that behave that way, someone will
> create one.
> --
>     --Andrew Koenig
>       ark@europa.att.com

It is not only an implementation issue, but aslo a language design issue.
The key thing is that WHY template users NEED to have the access to the
template source. Such need comes from the template itself, not from any
particular implementation. If the concept of template is not improved in
language design, it is impossible to write a compiler that can hide the
template source code from the user.

David Shang





Author: shang@corp.mot.com (David (Lujun) Shang)
Date: Tue, 6 Oct 92 01:19:51 GMT
Raw View
In article <23808@alice.att.com> ark@alice.att.com (Andrew Koenig) writes:
> In article <0enxJ1W00awTMNepU8@andrew.cmu.edu>, osoelgaultier+@CMU.EDU
(Stefan Monnier) writes:
>
> > As are currently implemented templates, you don't know
> > anything about the actual type at compile-time.
> > So that no method calls or variable accesses can be compiled
> > for any variable of 'template type'.
>
> But you still haven't answered my question.
>
> My question was: what reason do you have to believe that
> adding inheritance constraints would solve the problem?
>
> In thinking about the answer, don't forget about inline functions.
> --
>     --Andrew Koenig
>       ark@europa.att.com

Please note that a constrained parameterized class is a completely
different language concept from C++ template, though it can replace the
template concept anyway.

A constrained parameterized class is an abstract class. You need not to
"instantiate" it before using it. Compilers can generate real executable
codes for member functions defned in a constrained parameteried class.
Once a parameterized class is compiled separately, the compiler can
ensure no type-error related to the usage of the class parameters.
Therefore, there is no need to expose the source code to the user. What
the user need to prove is that whether his/her actual parameter is
conformable to the class parameter specification. For library-developers,
since the code is already generated by the compiler and built into a
library, it is no longer needed for them to ship the source code with
their products.

Inline functions are an independent language issue.

David Shang






Author: shang@corp.mot.com (David (Lujun) Shang)
Date: Tue, 6 Oct 92 02:00:42 GMT
Raw View
In article <1992Oct5.160022.29224@genghis.borland.com> pete@genghis.borland.com
(Pete Becker) writes:
>
>  But this has very little to do with templates.  Constrained parameters
> and no further knowledge of the actual type is equivalent, as far as I can
> see, to simply carrying around a pointer to the actual class, and dealing
> with it only through the known interface.  You don't need templates to
> implement this, and I don't see that there's anything gained by using the
> template mechanism to do it.

Really? In my O-O design experience, it is very common to have a generic
model which is composed of several sub-models:

   M < SM1, SM2, SM3 >

and then use the genric model to produce another generic model M':

   M' < SM1', SM2', SM3' >

with more detailed specification. Sub-models in M' are usually covariantly
specified. As far as I can see, only constrained parameterized class can
support this concept. Sure, we can use pointers or even void* to implement
this concept, but it is never a serious programming style. To be honest, I
did not implement this concept in template (it's hard to figure out how can
template to support this), instead, I use pointers. But I have to use
expressions like:

    ((Derived*)->foo((DeriveInput*) input);
    ((SubDerived*)(((Derived*)->sub_model)->)->sub_foo();
    ((SubSubDerived*)(((SubDerived*)((((Derived*)->sub_model)->)->...;
    ...

How ugly they are!

>  Templates avoid the extra indirection that's needed when you don't
> know what type you're dealing with.

It is an implementation issue. Eiffel uses pointers to access to members of
the type which is a parameter. There is an alternative way to implement
them without indirection. Indirection is required only when the polymorphism
is used. For example:

  class BaseList < class EleType[Base], int size >
  { public:     // make data member public for simplifying the example
      EleType eles[size];
  };

  BaseList * bl;
  BaseList<class EleType=Derived, size=10> dl;
  bl = &dl;

  bl->eles[2];  // dynamically computing the size of EleType is required
  dl.eles[2];   // address is computed statically

Constrained parameterized classes does not necessarily have extra
indirection. Indirection is needed only when polymorphism based on
the parameterized classes is required. And such polymorphism is NOT
supported by C++ templates.

David Shang








Author: ark@alice.att.com (Andrew Koenig)
Date: 6 Oct 92 17:45:37 GMT
Raw View
In article <Yeo91je00awVE_zEkI@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:

> What I say is just that inheritance constraint permits to check
> the file and compile it before using it !

I understand that that is what you're saying, but you haven't convinced me.

For example, suppose we have a class:

 class Foo {
 public:
  void mem(int);
 };

and a template function:

 template<class T> void f(T t) { t.mem(0); }

You are saying that constraining T to be of class Foo or a class
derived from Foo will make it possible to type-check this template
at compile time.  Wel, what about this?

 class Bar: public Foo {
 public:
  void mem(int);
  void mem(void*);
 };

If we call f with an argument of type Bar, it will fail during instantiation
with an ambiguity error.  The only way to avoid this is to say that the type
constraint also constrains the call of t.mem(0) to just those instances of
mem defined in the base class -- but in that case, you will still get in
trouble with this one:

 class Baz: public Foo {
 public:
  void mem(long);
  void mem(double);
 };

because now *neither* of the variants of Baz::mem matches the one in Foo.
Thus, you have two choices:

 1. Attempt to call Baz::mem(int), which doesn't exist;

 2. Call Foo::mem(int), in which case you might as well not
    bother using templates at all, or

 3. Give an ambiguity error, in which case you can't type-check
    the original template.

My point in giving this example is to show that statements like `constraining
template types makes compile-time type checking possible' cannot be made
casually -- it is the responsibility of the person making such a statement
to provide evidence that the statement is indeed true.

This stuff is **difficult**!  Don't take it lightly!
--
    --Andrew Koenig
      ark@europa.att.com




Author: pete@genghis.borland.com (Pete Becker)
Date: Tue, 6 Oct 1992 17:27:54 GMT
Raw View
In article <Yeo91je00awVE_zEkI@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:
>
>With inheritance constraints, you can restrict method calls
>to those known to be present (through inheritance).
>Inlining doesn't make it impossible: it's just harder, cause
>you can't keep the compiled version in pure object code, but
>you have to keep information on where are the 'parameters' used
>in order to translate their use !
>
>What I say is just that inheritance constraint permits to check
>the file and compile it before using it !
>

 Constrained inheritance in combination with compiling before use
also constrains you to a subset of the current template functionality which
can be implemented without any notion of templates.  All you have to do is
write a class that uses pointers to the actual object, and restricts its
method calls to those "known to be present".  One of the major benefits of
templates arises precisely because they depend on the actual class used: the
compiler can generate much better code when it "knows" what it's dealing with.
 -- Pete





Author: pete@genghis.borland.com (Pete Becker)
Date: Tue, 6 Oct 1992 17:41:29 GMT
Raw View
In article <1992Oct6.020042.11130@cadsun.corp.mot.com> shang@corp.mot.com writes:
>In article <1992Oct5.160022.29224@genghis.borland.com> pete@genghis.borland.com
>(Pete Becker) writes:
>>
>>  But this has very little to do with templates.  Constrained parameters
>> and no further knowledge of the actual type is equivalent, as far as I can
>> see, to simply carrying around a pointer to the actual class, and dealing
>> with it only through the known interface.  You don't need templates to
>> implement this, and I don't see that there's anything gained by using the
>> template mechanism to do it.
>
>Really? In my O-O design experience, it is very common to have a generic
>model which is composed of several sub-models:
>
>   M < SM1, SM2, SM3 >
>
>and then use the genric model to produce another generic model M':
>
>   M' < SM1', SM2', SM3' >
>
>with more detailed specification.

 I seem to have not made myself clear.  What I was responding to was
the claim that constrained parameters ALLOW THE TEMPLATE DEFINITION TO BE
COMPILED INDEPENDENTLY OF ANY PARTICULAR INSTANTIATION.  While that's
certainly true, it offers very little beyond what's currently available
without using templates, precisely because the compiler knows nothing about
the actual types of the template parameters.
 If you want constrained templates AND independent compilation of
template definitions, you've already got it.  But don't call it a template.
Call it a forwarding class.
 -- Pete




Author: osoelgaultier+@CMU.EDU (Stefan Monnier)
Date: 6 Oct 92 23:25:36 GMT
Raw View
Excerpts from netnews.comp.lang.c++: 6-Oct-92 Re: The concept of
template.. Pete Becker@genghis.borl (1483)
>  I seem to have not made myself clear.  What I was responding to was
> the claim that constrained parameters ALLOW THE TEMPLATE DEFINITION TO BE
> COMPILED INDEPENDENTLY OF ANY PARTICULAR INSTANTIATION.  While that's
> certainly true, it offers very little beyond what's currently available
> without using templates, precisely because the compiler knows nothing about
> the actual types of the template parameters.
>  If you want constrained templates AND independent compilation of
> template definitions, you've already got it.  But don't call it a template.
> Call it a forwarding class.
>  -- Pete


The point with templates in general, IMHO (but I believe it's shared
by others), is to to be able to typecheck. Else, a pointer to void with
some casts could do the trick.

template <class T> T hello(T t)

is not the same as

T hello(T t)

cause if you call hello with a type Hi (which inherit from T), you know
that it will return an object of type Hi, whereas without templates,
this is not checked: It can return any object of type T (maybe it is also of
type Hi, but no typechecking occurs here: you're only responsible for it)

Constraints templates doesn't change anything to this fact. The only
thing it changes is that the internals of a function (or anything else)
depending on a template (like hello) can be checked (and compiled)
before using it: separately !

If it has some speed drawbacks (cause it is harder to fully optimize
(although possible)), I don't really care: the difference may not be that big
(and if you really care about top-speed, use plain C or assembler or avoid
templates and typecheck yourself)

 Stefan

-----------------------------------------------------
-- On the average, people seem to be acting normal --
-----------------------------------------------------




Author: Stefan Monnier <osoelgaultier+@CMU.EDU>
Date: Tue, 6 Oct 1992 19:31:26 -0400
Raw View
Excerpts from netnews.comp.lang.c++: 6-Oct-92 Re: The concept of
template.. Andrew Koenig@alice.att. (1825)
> If we call f with an argument of type Bar, it will fail during instantiation
> with an ambiguity error.  The only way to avoid this is to say that the type
> constraint also constrains the call of t.mem(0) to just those instances of
> mem defined in the base class -- but in that case, you will still get in
> trouble with this one:

>  class Baz: public Foo {
>  public:
>   void mem(long);
>   void mem(double);
>  };

> because now *neither* of the variants of Baz::mem matches the one in Foo.
> Thus, you have two choices:

>  1. Attempt to call Baz::mem(int), which doesn't exist;

>  2. Call Foo::mem(int), in which case you might as well not
>     bother using templates at all, or

>  3. Give an ambiguity error, in which case you can't type-check
>     the original template.

> My point in giving this example is to show that statements like `constraining
> template types makes compile-time type checking possible' cannot be made
> casually -- it is the responsibility of the person making such a statement
> to provide evidence that the statement is indeed true.

> This stuff is **difficult**!  Don't take it lightly!
> --
>     --Andrew Koenig
>       ark@europa.att.com

What's the problem ?

Why not take option 2 ?

Every Baz object has method Foo::mem(int) cause it has inherited it
from Foo.
If you don't agree with it, why use inheritance ?

And if you would like it to call anything else, then you programming
style seems weird to me !!!

 Stefan

-----------------------------------------------------
-- On the average, people seem to be acting normal --
-----------------------------------------------------









Author: ark@alice.att.com (Andrew Koenig)
Date: 7 Oct 92 12:52:17 GMT
Raw View
In article <IeoW7Ca00awVEGbFIn@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:

> What's the problem ?

> Why not take option 2 ?

> Every Baz object has method Foo::mem(int) cause it has inherited it
> from Foo.
> If you don't agree with it, why use inheritance ?

Well, let's make it more explicit.

 class Foo {
 public:
  void mem(int);
 };

 class Bar: public Foo {
 public:
  void mem(int);
 };

 template<class T> void f(T x) { x.mem(); }

 main()
 {
  Bar b;
  f(b);
 }

The whole point of templates is that the call f(b) should result in
calling Bar::mem, because b is an object of type Bar.

What you're saying is that you want f(b) to call Foo::mem if the template
function f has a constraint that T is Foo or derived from Foo.
It's already easy to obtain such behavior -- just don't bother with
templates at all!

In other words, I don't think option 2 is viable.  Do you still think
so after seeing this example?
--
    --Andrew Koenig
      ark@europa.att.com




Author: pete@genghis.borland.com (Pete Becker)
Date: Wed, 7 Oct 1992 17:03:51 GMT
Raw View
In article <UeoW1kS00awV0GbEpY@andrew.cmu.edu> Stefan Monnier <osoelgaultier+@CMU.EDU> writes:
>
>The point with templates in general, IMHO (but I believe it's shared
>by others), is to to be able to typecheck. Else, a pointer to void with
>some casts could do the trick.
>
>template <class T> T hello(T t)
>
>is not the same as
>
>T hello(T t)
>
>cause if you call hello with a type Hi (which inherit from T), you know
>that it will return an object of type Hi, whereas without templates,
>this is not checked: It can return any object of type T (maybe it is also of
>type Hi, but no typechecking occurs here: you're only responsible for it)
>
>Constraints templates doesn't change anything to this fact. The only
>thing it changes is that the internals of a function (or anything else)
>depending on a template (like hello) can be checked (and compiled)
>before using it: separately !
>

 Constrained parameters alone do not make it possible to compile a
template without regard to how it will be instantiated.

 class Parameter
 {
 public:
     virtual void f( long );
 };

 template <class T : Parameter>
 class DoSomething
 {
 };

 class SmartParameter : public Parameter
 {
 public:
     void f( long );
     void f( int );
 };

Presumably, SmartParameter adds f(int) because it can handle small values
in a more efficient manner.  If DoSomething is compiled without knowledge of
the actual template parameter being used, this smarter interface is lost.
 As I mentioned earlier, the other place where you pay for this is that
all uses of the template parameter must be through pointers.
 Being able to compile a template without knowing how it is in fact
being used may well be useful, but it comes at a price.  The resulting code
will be less efficient.
 I think the argument in favor of compiling templates on their own has
to focus on this point.  What do you get out of it that you cannot get by
simply using pointers?  Easier coding, sure.  But are there significant
differences in the kind of things you can do with them?  Or is this a solution
in search of a problem?
 -- Pete




Author: shang@corp.mot.com (David (Lujun) Shang)
Date: Wed, 7 Oct 92 15:05:01 GMT
Raw View
In article <23822@alice.att.com> ark@alice.att.com (Andrew Koenig) writes:
> For example, suppose we have a class:
>
>  class Foo {
>  public:
>   void mem(int);
>  };
>
> and a template function:
>
>  template<class T> void f(T t) { t.mem(0); }
>

I soppose f is defined as:

     <class T[Foo]> void f(T t) { t.mem(0); };

where keyword template is not necessary, because "f" can be called
directly without any instantiation.

> You are saying that constraining T to be of class Foo or a class
> derived from Foo will make it possible to type-check this template
> at compile time.  Wel, what about this?
>
>  class Bar: public Foo {
>  public:
>   void mem(int);
>   void mem(void*);
>  };
>
> If we call f with an argument of type Bar, it will fail during instantiation
> with an ambiguity error.

I suppose "mem" defined in Foo is a virtual function, otherwise "t.mem(0)"
will always call the "mem" defined in Foo.

Calling f with an argument of type Bar causes no ambiguity. The actual
member function called is the "mem" that overrides the virtual "mem (int)"
defined in Foo.

> The only way to avoid this is to say that the type
> constraint also constrains the call of t.mem(0) to just those instances of
> mem defined in the base class

Not necessarily. Constrained parameterized function is not a template
function. It does not necessarily act exactly like a template, just as a
 template function does not necessarily act exactly like a macro definition.

> -- but in that case, you will still get in
> trouble with this one:
>
>  class Baz: public Foo {
>  public:
>   void mem(long);
>   void mem(double);
>  };
>

No trouble. Foo::mem(int) will be called because you did not override it.

> This stuff is **difficult**!  Don't take it lightly!

Agree. But it is not a novel stuff.


David Shang






Author: shang@corp.mot.com (David (Lujun) Shang)
Date: Wed, 7 Oct 92 15:53:29 GMT
Raw View
In article <1992Oct6.174129.10404@genghis.borland.com> pete@genghis.borland.com
(Pete Becker) writes:
>  I seem to have not made myself clear.  What I was responding to was
> the claim that constrained parameters ALLOW THE TEMPLATE DEFINITION TO BE
> COMPILED INDEPENDENTLY OF ANY PARTICULAR INSTANTIATION.  While that's
> certainly true, it offers very little beyond what's currently available
> without using templates, precisely because the compiler knows nothing about
> the actual types of the template parameters.

I'm afraid I misunderstand what you claimed here. I can't understand
this statement: "it offers very little beyond what's currently available
without using templates, precisely because the compiler knows nothing
aboutthe actual types of the template parameters", would you offer an
example? I refer "it" in your statement to a constrained parameterized
class (template). If the class parameter is constrained, the compiler
should know a partial interface of the parameter, and all the usage of
the parameter should obey the protocol described in the partial interface.
If you need to know the further detail about the interface, you can
re-constrain (narrow) the parameter in the derived classes. That is the
specialization, which I view a mechanism as useful as inheritance.

Constrained parameterized classes offer much more than separate
compilation. I just list a few more points here:

1. It supports specialization and covariant specification;
2. It supports polymorphism (dynamic binding) based on parameterization;
3. It supports more precise interface specification (type dependency);
4. It supports code reuse not only at the source level, but also at the
   machine code level.

>  If you want constrained templates AND independent compilation of
> template definitions, you've already got it.  But don't call it a template.
> Call it a forwarding class.

Exactly. See, I call it a constrained parameterized class and never
call it a template. In fact, a constrained parameterized class IS a
class, it can be used anywhere as an abstract class is used. Therefore,
it is NOT a template. For exmaple:

  class < class MemberT[GroupMember] > Group {...};

You can use Group to declare a pointer or a function argument:

  Group * group;
  group = new Group <class MemberT=SomeMemberType> (...);

or,

  void foo (Group & group);

You cannot use template this way.

The same case with constrained parameterized function:

  <Group GT> GT.MemberT select_one (const GT & group);

and "select_one" can be called directly: "select_one(aDogGroup)" will return a
dog; "select_one(aCatGroup)" will return a cat.

David Shang





Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Thu, 8 Oct 1992 03:53:46 GMT
Raw View
In article <1992Oct6.011951.10984@cadsun.corp.mot.com> shang@corp.mot.com writes:
>In article <23808@alice.att.com> ark@alice.att.com (Andrew Koenig) writes:
>> In article <0enxJ1W00awTMNepU8@andrew.cmu.edu>, osoelgaultier+@CMU.EDU
>(Stefan Monnier) writes:
>>
>> > As are currently implemented templates, you don't know
>> > anything about the actual type at compile-time.
>> > So that no method calls or variable accesses can be compiled
>> > for any variable of 'template type'.
>>
>> But you still haven't answered my question.
>>
>> My question was: what reason do you have to believe that
>> adding inheritance constraints would solve the problem?
>>
>> In thinking about the answer, don't forget about inline functions.
>> --
>>     --Andrew Koenig
>>       ark@europa.att.com
>
>Please note that a constrained parameterized class is a completely
>different language concept from C++ template, though it can replace the
>template concept anyway.
>
>A constrained parameterized class is an abstract class. You need not to
>"instantiate" it before using it. Compilers can generate real executable
>codes for member functions defned in a constrained parameteried class.
>Once a parameterized class is compiled separately, the compiler can
>ensure no type-error related to the usage of the class parameters.
>Therefore, there is no need to expose the source code to the user. What
>the user need to prove is that whether his/her actual parameter is
>conformable to the class parameter specification. For library-developers,
>since the code is already generated by the compiler and built into a
>library, it is no longer needed for them to ship the source code with
>their products.
>

 We already have abstract classes that are precisely what
you want. A generic class even with constraints CANNOT generate
actual code until instantiated. But it CAN be type checked
at compile time.

 Restricting a generic parater to a Base class is pointless.
It only allows you to generate actual code in precisely those
cases where you didn't need a template in the first place.

 I think there are two types of templates:

 1) completely unconstrained. Actually, there is no
 such thing, there ARE constraints, but they are implicit
 in the source of the defintion.

 2) completely constrained. In this case you have to
 list all the properties of the parameters and even
 some relations between them.

 This implies you can completely type check the template
 definition. And thus, you can give meaningful error messages
 (constraint xxx violated) when you do a bad instantiation.

 But you still cant fully compile code.

 Or can you? Suppose the constraints were global functions.
 The the generic procedure would take some hidden
 parameters, these being the address of these functions.

 Mm. For data members, it would have to be say the offset,
 and for member functio the address (or, for virtuals,
 something more ...)

 The problem might be that something so comletely constrained
 would be less useful than unconstrained genericity.
 For example, it would not be enough to say T has a data member
 'number' which was numeric to add it to something. You would
 have to say it was 'int'.

 If the really tight constraints I propose are provided,
 you could perhaps compile a generic function.

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: osoelgaultier+@CMU.EDU (Stefan Monnier)
Date: 8 Oct 92 12:51:42 GMT
Raw View
Excerpts from netnews.comp.lang.c++: 7-Oct-92 Re: The concept of
template.. Pete Becker@genghis.borl (2093)
>  Constrained parameters alone do not make it possible to compile a
> template without regard to how it will be instantiated.

>  class Parameter
>  {
>  public:
>      virtual void f( long );
>  };

>  template <class T : Parameter>
>  class DoSomething
>  {
>  };

>  class SmartParameter : public Parameter
>  {
>  public:
>      void f( long );
>      void f( int );
>  };

> Presumably, SmartParameter adds f(int) because it can handle small values
> in a more efficient manner.  If DoSomething is compiled without knowledge of
> the actual template parameter being used, this smarter interface is lost.
>  As I mentioned earlier, the other place where you pay for this is that
> all uses of the template parameter must be through pointers.
>  Being able to compile a template without knowing how it is in fact
> being used may well be useful, but it comes at a price.  The resulting code
> will be less efficient.
>  I think the argument in favor of compiling templates on their own has
> to focus on this point.  What do you get out of it that you cannot get by
> simply using pointers?  Easier coding, sure.  But are there significant
> differences in the kind of things you can do with them?  Or is this a solution
> in search of a problem?
>  -- Pete


Who said there was no drawbacks ?

Of course it may add some overhead (although development will be nicer cause
of typechecking and FASTER turn around time (though precompiled template
libraries))

Every advance in languages has been associated with an increased overhead:
from assembler to C, from C to C++: every time you switch to a higher level
language you lose some speed.

I don't think particular change will add a big overhead. that's why I
think it's useful !

 Stefan

-----------------------------------------------------
-- On the average, people seem to be acting normal --
-----------------------------------------------------




Author: osoelgaultier+@CMU.EDU (Stefan Monnier)
Date: 8 Oct 92 12:43:58 GMT
Raw View
Excerpts from netnews.comp.lang.c++: 7-Oct-92 Re: The concept of
template.. Andrew Koenig@alice.att. (991)

> In article <IeoW7Ca00awVEGbFIn@andrew.cmu.edu> osoelgaultier+@CMU.EDU
> (Stefan Monnier) writes:

> > What's the problem ?

> > Why not take option 2 ?

> > Every Baz object has method Foo::mem(int) cause it has inherited it
> > from Foo.
> > If you don't agree with it, why use inheritance ?

> Well, let's make it more explicit.

>  class Foo {
>  public:
>   void mem(int);
>  };

>  class Bar: public Foo {
>  public:
>   void mem(int);
>  };

>  template<class T> void f(T x) { x.mem(); }

>  main()
>  {
>   Bar b;
>   f(b);
>  }

> The whole point of templates is that the call f(b) should result in
> calling Bar::mem, because b is an object of type Bar.

> What you're saying is that you want f(b) to call Foo::mem if the template
> function f has a constraint that T is Foo or derived from Foo.
> It's already easy to obtain such behavior -- just don't bother with
> templates at all!

> In other words, I don't think option 2 is viable.  Do you still think
> so after seeing this example?
> --
>     --Andrew Koenig
>       ark@europa.att.com


Sorry, but the original problem was a bit different, cause it uses overloading:


-For example, suppose we have a class:
-
- class Foo {
- public:
-  void mem(int);
- };
-
-and a template function:
-
- template<class T> void f(T t) { t.mem(0); }
-
-You are saying that constraining T to be of class Foo or a class
-derived from Foo will make it possible to type-check this template
-at compile time.  Wel, what about this?
-
- class Bar: public Foo {
- public:
-  void mem(int);
-  void mem(void*);
- };
-
-If we call f with an argument of type Bar, it will fail during instantiation
-with an ambiguity error.  The only way to avoid this is to say that the type
-constraint also constrains the call of t.mem(0) to just those instances of
-mem defined in the base class -- but in that case, you will still get in
-trouble with this one:
-
- class Baz: public Foo {
- public:
-  void mem(long);
-  void mem(double);
- };
-

Here, I suggested to call Foo::mem(int) (or Bar::mem(int) if it exists) cause,
at compile time, mem(0) can only be linked to mem(int) (the others are
unknown) and because there  is no reason to link it to anything else (in
fact, the only other alternative I can see is to announce an ambiguity)

But of course if the inherited method is overridden, the new one should
be called
(but a method with same name but different arguments is not considered to be
the same method: it's not overriden)

 Stefan

-----------------------------------------------------
-- On the average, people seem to be acting normal --
-----------------------------------------------------




Author: ark@alice.att.com (Andrew Koenig)
Date: 9 Oct 92 13:42:06 GMT
Raw View
In article <Eep9xSi00Vp_4391Iw@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:

> Who said there was no drawbacks ?

You implied it, by not mentioning any earlier.
--
    --Andrew Koenig
      ark@europa.att.com




Author: pete@genghis.borland.com (Pete Becker)
Date: 9 Oct 92 17:38:21 GMT
Raw View
In article <Eep9xSi00Vp_4391Iw@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:
>>
>>  I think the argument in favor of compiling templates on their own has
>> to focus on this point.  What do you get out of it that you cannot get by
>> simply using pointers?  Easier coding, sure.  But are there significant
>> differences in the kind of things you can do with them?  Or is this a solution
>> in search of a problem?
>>  -- Pete
>
>
>Who said there was no drawbacks ?
>
>Of course it may add some overhead (although development will be nicer cause
>of typechecking and FASTER turn around time (though precompiled template
>libraries))
>
>Every advance in languages has been associated with an increased overhead:
>from assembler to C, from C to C++: every time you switch to a higher level
>language you lose some speed.
>
>I don't think particular change will add a big overhead. that's why I
>think it's useful !
>
> Stefan

 I'll repeat my question: what do you get out of it that you cannot get
by simply using pointers?  Simply asserting that it won't add big overhead does
not establish that it is useful.
 -- PEte




Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Fri, 9 Oct 1992 17:28:12 GMT
Raw View
In article <23822@alice.att.com> ark@alice.UUCP () writes:
>In article <Yeo91je00awVE_zEkI@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:
>
>> What I say is just that inheritance constraint permits to check
>> the file and compile it before using it !
>
>I understand that that is what you're saying, but you haven't convinced me.
>

 Me neither, but I haven't given up on the idea that you might just
be able to compile templates.

 Consider

 template<class T> f(T *t){t->print();}

The constraint is that T must have a member function 'print()'.
Now it seems that you can compile this routine, but you
have to replace 'print' with a pointer supplied silently as a
parameter to f. The call

 f(pObject);

is checked against the constraints, if it passes this test,
f is called with the pointer pObject AND the address of
its print routine.

More general cases would require the addresses of constructors
to be passed (i'm glossing over lots of issues here).

>
>My point in giving this example is to show that statements like `constraining
>template types makes compile-time type checking possible' cannot be made
>casually -- it is the responsibility of the person making such a statement
>to provide evidence that the statement is indeed true.
>
>This stuff is **difficult**!  Don't take it lightly!
>--
>    --Andrew Koenig
>      ark@europa.att.com

So I'm not making the claim it can be done, only throwing in
a suggesting of HOW it might be done. But I reject the notion
that the constraints should be named base classes, rather,
the constraints are the silent parameters mentioned
above, they are the 'functions' that the type T must
have. (Yes this is a crude description, its just an idea.
Can it be made to work, if not why not, if so what
we gain is type checked templates, we loose efficiency,
at least: what else, and is it worth it?)

BTW: the constraints of course DO form a kind of
abstract, unnamed, 'base' class that you *might* have
derived the type T from had you thought of it.


--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: nickn@manutius.UUCP (Nick Nussbaum)
Date: 10 Oct 92 22:29:09 GMT
Raw View
I'm looking for a c++ preprocessor that converts template notation into
macros for older c++ compilers. I recall seeing a mention of such about
a year ago. Does anyone have a reference?
Thanks.




Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Sun, 11 Oct 1992 13:37:04 GMT
Raw View
In article <Eep9xSi00Vp_4391Iw@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:
>
>Every advance in languages has been associated with an increased overhead:
>from assembler to C, from C to C++: every time you switch to a higher level
>language you lose some speed.
>

 Not true! Consider a language with assertion facilities,
the assertions get included as run-time checks. The program is
now 'correct', although you only get to catch errors at run-time.

 Now add an inference engine to the compiler. It might now
PROVE certain assertions, thus eliminating the run-time checks,
the result is faster and smaller. Further more is may show certain
assertions FALSE, thus improving the chances of catching errors
in parts of the code that are not exercised often.

 This would be a major advance IMHO, and it results
in faster code as well as earlier error detection.

 Now consider virtual functions. If you are losing
speed, dont use a virtual. But you need a virtual? Well,
then virtuals are surely faster than an equivalent handcoded
indirect call.

 There are FORTRAN compiler around for which it is claimed
that they produce better code than hand coded assembler. So I think
you have overgeneralised a bit in your claim that advances have
run-time speed costs.

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Fri, 2 Oct 1992 15:38:26 GMT
Raw View
In article <1992Oct1.140643.9775@cadsun.corp.mot.com> shang@corp.mot.com writes:
>
>Thank you, Raymond, for raising this thread. I'd like to fork it
>to comp.std.c++ for standard committee to reconsider whether template should be
>accepted as C++ standard.

 How would you modify the template idea to be better?

>
>In article <stefans.717754437@bauv106> stefans@bauv106.bauv.unibw-muenchen.de
>(Stefan Schwarz) writes:
>
>> Would be interesting to hear from library-developers about shipping their
>> products together with source-code.
>
>Right to the point. Would be interesting also to hear about from the
>library-users about reading the source code to detect where are the source of
>the usage error.
>
>Template is not a self-enclosed type-safe language feature, i.e. it cannot be
>compiled separately to ensure type-error free. All type errors about the class
>parameters are checked when the template is used. When the library-developers
>ship their products, they cannot ensure their templates are type-error free.

 This is not true, of course they can. What you mean
is that the compiler doesn't help very much, and I agree.
But I'm sure one could prove that a template was error free
by hand ( I agree this is not formal system like a compiler check,
but lets not get into whether a proof actually proves what it purports
to or not: the usual solution to this problem is to publish the
proof ).

>The library user will get confused when an error is reported on the source code
>of the template: "should it be my fault or the fault of the template itself?"
>
>In sense of the relationship between developer and user, template is something
>like untyped function (I don't refer to run-time type error).
>
>David Shang

 I agree but am too stupid to see how the situation could be
improved. For a template class C, it will be the case that

 C<T1>  makes sense
 C<T2>  is illegal

depending on T1 and T2. One cant check that until use, unless
perhaps you have to predeclare:

 class C<T1>; // causes expansion NOW!

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: shang@corp.mot.com (David (Lujun) Shang)
Date: Fri, 2 Oct 92 14:49:59 GMT
Raw View
From: shang@corp.mot.com (David (Lujun) Shang)
Newsgroups: comp.std.c++,comp.lang.c++
Subject: Re: The concept of templates considered ill designed
References: <1992Oct1.140643.9775@cadsun.corp.mot.com>
Reply-To: shang@corp.mot.com

In article <1992Oct1.140643.9775@cadsun.corp.mot.com> shang@corp.mot.com I
wrote:
> Template is not a self-enclosed type-safe language feature, i.e. it cannot be
> compiled separately to ensure type-error free. All type errors about the
> class parameters are checked when the template is used. When the
> library-developers ship their products, they cannot ensure their templates
> are type-error free. The library user will get confused when an error is
> reported on the source code of the template: "should it be my fault or the
> fault of the template itself?"
>

I'd like to add something more. When OO models are designed with many
templates nested and derived, they really messed up the whole system
if temaplates cannot be self-ensured type-correct. I've used templates
to write many generic models. It's almost a nightmare for me to trace
the error when templates are nested and with three or four derived
depth in sperated files. It's okay for me because I'm both the template
writer and the template user. But how about when the templates are
shipped to users with a library?

Another major defect with C++ template is that the template does not
support specialization. I view specialization is as important as
inheritance in OO design. We use template mainly for specifying an
abstract class with some generic features. In most cases, these
generic features are vague for a general tempalte. As special
templates derived, the generic features becomes more and more
clear. Therefore, template specification should be able to describe
and  precise generic features step by step. Unfortunately C++
template applies unconstrained class parameters, which not only
leaves tempalte an imperfect feature in sense of type-safeness,
but also disables specialization.

Many models need specialization. Without language supported
specialization, we have to use many nasty unsafe downcast in
the program. The worse thing is that the programmers or the users
must keep in mind that something has virtually been specialized but
there is no way to protect them from passing a general object to a
virtually specialized interface.

Can C++ templates be improved? Sure. The concept of constrained
classes has been applied in some other OO languages. Why can't C++
apply it? Of cause there are some technical difficulties to integrate
the concept of multiple inheritance and the concept of the
constrained parameterization in C++. But it does not mean this
integration is imppossible.

A constrained parameterized class is a self-enclosed type-safe entity.
It can be compiled separately to ensure type-correctness.

A constrained parameterized class can be used as an abstract class.
Its implementation be separated from its definition. The
implementation code need not be exposed to the user, and the user
need not the check the implementation code to locate the error.

Constrained parameterized classes support specialization, therefore,
MammalGroup<MemberType[Mammal]> is a specialized class of
AnimalGroup<MemberTyep[Animal]>, you can specialize your template
models step by step.

Constrained parameterized classes are real classes, and you can
achieve polymorphism based on specialization (the current C++ can
only achieve polymorphism on inheritance). For example, I need a
generic object storage model like:


                          specialization
 Reference --------------------------------------------------------->
   |
   |      reference
  i|      |      |
  n|   pointer---|------ > pointer<list> --> pointer<ordered_list> ->
  h|       persistant_ref --> pref<list> --> pref<ordered_list> -->
  e|             |  (pref)
  r|             |
  i|      synchronized_ref --> sref<list> --> sref<ordered_list> -->
  t|             |  (sref)
  a|             |
  n|       recvorable_ref --> rref<list> --> rref<ordered_list> -->
  c|                (rref)
  e|
   |
   v

So that I can use user-defined references in the way I use built-in
pointers. For example, I can use MS Windows' memery handle like
(the following programs are not written in C++):

class Base { public: virtual void vfoo(); };
class Derived1: public Base { public: virtual void vfoo(); };
class Derived2: public Base { public: virtual void vfoo(); };

class Handle < class ObjType >
      // unconstrained ObjType can be any type
{  protected:
      HANDLE h;
   public:
      ObjType * operator->() { ... }; // open the handle
      void * operator <-() { ... };   // close the handle
      thiscalss create( ObjType * ) { ... };  // create the handle
};
class BaseHandle: public Handle < class ObjType[Base] > {};
class Derived1Handle: public BaseHandle < class ObjType=Derived1 > {};
class Derived2Handle: public BaseHandle < class ObjType=Derived2 > {};

poly BaseHandle bh;  // a polymorphic handle, it must be initialized.
                     // BaseHandle is an abstract class, therefore
                     // "BaseHandle bh" is illeagal.
Derived1Handle d1h;
Derived2Handle d2h;
bh = d1h.create(new Derived1(...));
bh->vfoo(foo);  // should call class Derived1's vfoo
bh = d2h.create(new Derived2(...));
bh->vfoo(foo);  // should call class Derived2's vfoo

David Shang






Author: tmb@arolla.idiap.ch (Thomas M. Breuel)
Date: 3 Oct 92 09:07:15 GMT
Raw View
In article <1992Oct2.144959.18480@cadsun.corp.mot.com> shang@corp.mot.com (David (Lujun) Shang) writes:

   In article <1992Oct1.140643.9775@cadsun.corp.mot.com> shang@corp.mot.com I
   wrote:
   Template is not a self-enclosed type-safe language feature, i.e. it cannot be
   compiled separately to ensure type-error free. All type errors about the
   class parameters are checked when the template is used.

Yes. However, the reason for this is not intrinsic in the template
concept, but in the way templates were "integrated" with overloading
in C++.

     Thomas.




Author: pfbertra@watcgl.uwaterloo.ca (Philippe F. Bertrand)
Date: Sun, 4 Oct 1992 18:22:25 GMT
Raw View
In article <1992Oct2.153826.12051@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>In article <1992Oct1.140643.9775@cadsun.corp.mot.com> shang@corp.mot.com writes:
>>
>>Thank you, Raymond, for raising this thread. I'd like to fork it
>>to comp.std.c++ for standard committee to reconsider whether template should be
>>accepted as C++ standard.
>
> How would you modify the template idea to be better?

It would be nice if templates could have some sort of base class derivation
rules.  Ie instead of < class T > have <class Foo T> which restricts T to be
a class publicly derived from Foo.

Also for code hiding, compilers should generate intermediate files for
templated code so that user's of a template class do not need to have access
to the source.

- Philippe F. Bertrand                          pfbertrand@watcgl.uwaterloo.ca
Computer Graphics Lab, Department of Computer Science,
University of Waterloo, Waterloo, Canada  N2L 3G1




Author: ark@alice.att.com (Andrew Koenig)
Date: 4 Oct 92 21:34:56 GMT
Raw View
In article <BvM0DE.EA7@watcgl.uwaterloo.ca> pfbertra@watcgl.uwaterloo.ca (Philippe F. Bertrand) writes:

> Also for code hiding, compilers should generate intermediate files for
> templated code so that user's of a template class do not need to have access
> to the source.

This is primarily an implementation issue, not alnaugae issue.
If enough people want compilers that behave that way, someone will
create one.
--
    --Andrew Koenig
      ark@europa.att.com




Author: osoelgaultier+@CMU.EDU (Stefan Monnier)
Date: 4 Oct 92 14:41:00 GMT
Raw View
Excerpts from netnews.comp.lang.c++: 4-Oct-92 Re: The concept of
template.. Andrew Koenig@alice.att. (466)

> In article <BvM0DE.EA7@watcgl.uwaterloo.ca> pfbertra@watcgl.uwaterloo.ca
> (Philippe F. Bertrand) writes:

> > Also for code hiding, compilers should generate intermediate files for
> > templated code so that user's of a template class do not need to have access
> > to the source.

> This is primarily an implementation issue, not alnaugae issue.
> If enough people want compilers that behave that way, someone will
> create one.
> --
>     --Andrew Koenig
>       ark@europa.att.com


I'm not so sure it is only an implementation issue.
But the suggested 'templates with type constraint' would
permit to change it into an implementation issue. (it the
way chosen for Eiffel)

 Stefan

-----------------------------------------------------
-- On the average, people seem to be acting normal --
-----------------------------------------------------




Author: ark@alice.att.com (Andrew Koenig)
Date: 5 Oct 92 02:44:53 GMT
Raw View
In article <Ienr=wm00awU8A=Ecc@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:

> But the suggested 'templates with type constraint' would
> permit to change it into an implementation issue.

Really?  Why do you think so?
--
    --Andrew Koenig
      ark@europa.att.com




Author: osoelgaultier+@CMU.EDU (Stefan Monnier)
Date: 4 Oct 92 21:40:17 GMT
Raw View
Excerpts from netnews.comp.lang.c++: 5-Oct-92 Re: The concept of
template.. Andrew Koenig@alice.att. (287)

> In article <Ienr=wm00awU8A=Ecc@andrew.cmu.edu> osoelgaultier+@CMU.EDU
> (Stefan Monnier) writes:

> > But the suggested 'templates with type constraint' would
> > permit to change it into an implementation issue.

> Really?  Why do you think so?
> --
>     --Andrew Koenig
>       ark@europa.att.com


As are currently implemented templates, you don't know
anything about the actual type at compile-time.
So that no method calls or variable accesses can be compiled
for any variable of 'template type'.

The only thing you can do at compile-time with those variables
is to store them and retrieve them in a structure, but, again,
without making them execute anything.

A hashtable (which requires the type to have at least a
'hash' method) couldn't be compiled, as the compiler
can know where the 'hash' method will be in the actual type !

That's why Eiffel has those type constraints: it's not a feature,
it's just necessary to be able to compile it separately ! (and to
typecheck separately also)

 Stefan

-----------------------------------------------------
-- On the average, people seem to be acting normal --
-----------------------------------------------------




Author: dag@control.lth.se (Dag Bruck)
Date: Mon, 5 Oct 1992 06:41:49 GMT
Raw View
In <comp.lang.c++,comp.std.c++> pfbertra@watcgl.uwaterloo.ca (Philippe F. Bertrand) writes:
>
>It would be nice if templates could have some sort of base class derivation
>rules.  Ie instead of < class T > have <class Foo T> which restricts T to be
>a class publicly derived from Foo.

It would also be useful if you could specify for example that
"assignment must be defined for T," without tying that knowledge to a
class hierarchy; assignment is also defined for built-in types which
cannot be classified by C++ classes.

I have seen some "interesting" examples of dummy template functions
that test class relations and if a member function exists.  It
unquestionably does the trick, but is it ugly!

  -- Dag




Author: ark@alice.att.com (Andrew Koenig)
Date: 5 Oct 92 15:57:54 GMT
Raw View
In article <0enxJ1W00awTMNepU8@andrew.cmu.edu>, osoelgaultier+@CMU.EDU (Stefan Monnier) writes:

> As are currently implemented templates, you don't know
> anything about the actual type at compile-time.
> So that no method calls or variable accesses can be compiled
> for any variable of 'template type'.

But you still haven't answered my question.

My question was: what reason do you have to believe that
adding inheritance constraints would solve the problem?

In thinking about the answer, don't forget about inline functions.
--
    --Andrew Koenig
      ark@europa.att.com




Author: pete@genghis.borland.com (Pete Becker)
Date: Mon, 5 Oct 1992 16:00:22 GMT
Raw View
In article <0enxJ1W00awTMNepU8@andrew.cmu.edu> osoelgaultier+@CMU.EDU (Stefan Monnier) writes:
>Excerpts from netnews.comp.lang.c++: 5-Oct-92 Re: The concept of
>template.. Andrew Koenig@alice.att. (287)
>
>> In article <Ienr=wm00awU8A=Ecc@andrew.cmu.edu> osoelgaultier+@CMU.EDU
>> (Stefan Monnier) writes:
>
>> > But the suggested 'templates with type constraint' would
>> > permit to change it into an implementation issue.
>
>> Really?  Why do you think so?
>> --
>>     --Andrew Koenig
>>       ark@europa.att.com
>
>
>As are currently implemented templates, you don't know
>anything about the actual type at compile-time.
>So that no method calls or variable accesses can be compiled
>for any variable of 'template type'.
>
>The only thing you can do at compile-time with those variables
>is to store them and retrieve them in a structure, but, again,
>without making them execute anything.
>
>A hashtable (which requires the type to have at least a
>'hash' method) couldn't be compiled, as the compiler
>can know where the 'hash' method will be in the actual type !
>
>That's why Eiffel has those type constraints: it's not a feature,
>it's just necessary to be able to compile it separately ! (and to
>typecheck separately also)
>

 But this has very little to do with templates.  Constrained parameters
and no further knowledge of the actual type is equivalent, as far as I can see,
to simply carrying around a pointer to the actual class, and dealing with it
only through the known interface.  You don't need templates to implement this,
and I don't see that there's anything gained by using the template mechanism
to do it.
 Templates avoid the extra indirection that's needed when you don't
know what type you're dealing with.




Author: tmb@arolla.idiap.ch (Thomas M. Breuel)
Date: 6 Oct 92 00:01:13 GMT
Raw View
In article <1992Oct5.160022.29224@genghis.borland.com> pete@genghis.borland.com (Pete Becker) writes:

   [discussion of how to go about adding various forms of type constraints
   to template arguments deleted]

    But this has very little to do with templates.  Constrained parameters
   and no further knowledge of the actual type is equivalent, as far as I can see,
   to simply carrying around a pointer to the actual class, and dealing with it
   only through the known interface.  You don't need templates to implement this,
   and I don't see that there's anything gained by using the template mechanism
   to do it.

That's not true. Unlike when you rely on inheritance, you can use a
template with any type that has the needed operations defined on it.
The type doesn't have to inherit from some common base type. The type
doesn't even have to be a class/struct.

For example, it is quite frequent that people write numerical template
code that works with an object that is vaguely number like. You'd like
to be able to use it with the built-in numerical types, as well as any
user defined types, as well as any types from a commercial library.
None of those types will inherit from one another, or from a common
"Number" type, nor is it entirely trivial to make this happen.

Another important reason is efficiency. Templates will generate code
that is specialized for the exact types that I'm using.

A third reason is that for templates, unlike for "dealing with classes
through a known interface", I can express type relationships between
arguments, and between arguments and return types.

 template <class A> A f(A x,A y) { ... }

is a very different function from

 A g(A x,A y) { ... }

even if all the objects you hand to "f" are subtypes of "A".

Allowing constraints on template arguments has proven to be very
useful in other languages. I think such a feature would be very
important in C++ as well. I would like to see both inheritance based
constraints and signature based constraints.

     Thomas.