Topic: Recursive templates (was Borland templates (AAUGH!))


Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Sun, 3 Oct 1993 12:39:55 GMT
Raw View
In article <27tfamINN1fu@emx.cc.utexas.edu> jamshid@emx.cc.utexas.edu (Jamshid Afshar) writes:
>In article <rfgCDIuKu.81D@netcom.com>,
>Ronald F. Guilmette <rfg@netcom.com> wrote:
>>In article <2792mn$dsk@techbook.techbook.com>
>>deef@techbook.techbook.com (Derek Foster) writes:
> template <class T> class ListElem {
>   ListElem<T> * next;
>   T data;
> };
> template <class T> class ListIterator {
>   typedef ListElem<T> Elem;
>   Elem * ptr;
> };
> class Foo {
>   ListIterator<Foo> iter;  // compiler error: sizeof Foo unkown
> };
>
>>>[...] It seems to me that the compiler shouldn't even be
>>>trying to expand the template for ListElem, since my only reference to the
>>>ListElem type is to a POINTER to the type.[...]
>>
>>As far as the ARM is concerned, the conditions under which a template will
>>actually be instantiated are (I think) totally unspecified.  Most people
>>expect that code like:
>> template <class T> class TMPL { /* ... */ };
>> TMPL<int> object;
>>will cause the template to be instantiated (in full?) but (contrary to
>>popular belief) the C++ standardization committee seems to be leaning
>>in the direction of saying that such code SHOULD NOT cause a "complete"
>>instantiation of the template, and that it should instead cause some
>>sort of partial instantiation (an odd notion if I ever heard of one)
>>under which some of the *members* of TMPL (e.g. the function members)
>>do not in themselves get instantiated.
>
>"Most people"?  "Popular belief"?  Apparently Derek doesn't want full
>template expansion whenever a template is instantiated, and I know I
>certainly don't.  If the compiler performed full instantiation
>immediately upon encountering "TMPL<T>", mutually dependent class
>templates like Derek's and recursive templates would be impossible.

True.  Quite true.  I stand corrected.

The conventional wisdom seems to be that little (if anything) of a template
should actually get instantiated unless it is absolutely crystal clear that
there is a need to have it instantiated.  (This came as a surprize to me
when I first learned about it.)

--

-- Ronald F. Guilmette ------------------------------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: jamshid@emx.cc.utexas.edu (Jamshid Afshar)
Date: 23 Sep 1993 19:34:30 -0500
Raw View
In article <rfgCDIuKu.81D@netcom.com>,
Ronald F. Guilmette <rfg@netcom.com> wrote:
>In article <2792mn$dsk@techbook.techbook.com>
>deef@techbook.techbook.com (Derek Foster) writes:
 template <class T> class ListElem {
   ListElem<T> * next;
   T data;
 };
 template <class T> class ListIterator {
   typedef ListElem<T> Elem;
   Elem * ptr;
 };
 class Foo {
   ListIterator<Foo> iter;  // compiler error: sizeof Foo unkown
 };

>>[...] It seems to me that the compiler shouldn't even be
>>trying to expand the template for ListElem, since my only reference to the
>>ListElem type is to a POINTER to the type.[...]
>
>As far as the ARM is concerned, the conditions under which a template will
>actually be instantiated are (I think) totally unspecified.  Most people
>expect that code like:
> template <class T> class TMPL { /* ... */ };
> TMPL<int> object;
>will cause the template to be instantiated (in full?) but (contrary to
>popular belief) the C++ standardization committee seems to be leaning
>in the direction of saying that such code SHOULD NOT cause a "complete"
>instantiation of the template, and that it should instead cause some
>sort of partial instantiation (an odd notion if I ever heard of one)
>under which some of the *members* of TMPL (e.g. the function members)
>do not in themselves get instantiated.

"Most people"?  "Popular belief"?  Apparently Derek doesn't want full
template expansion whenever a template is instantiated, and I know I
certainly don't.  If the compiler performed full instantiation
immediately upon encountering "TMPL<T>", mutually dependent class
templates like Derek's and recursive templates would be impossible.
Remember the non-template version of Derek's code is possible (using
forward declarations).  Full, immediate expansion would also mean that
a List class template writer would have to choose to either not define
operator<<(ostream&,const List<T>&) or require that any user of
List<T> define a T output operator, whether the user outputs lists or
not.

>Once again, I would emphasize that (as far as I know) neither the ARM nor
>the current X3J16 working paper give precise rules which would make it
>possible for us to *either* say that Borland is doing it wrong, or that
>Borland is doing it right.  These questions simply haven't been settled yet.

I agree.  I suggest that anyone with an interest in this area email
their compiler writers with code that they expect to work.  Let them
know what most people desire.

I believe the following should also be legal:

 template<class Container> class Iter {
    Container* container;
    Container::IterState state;
 };
 template<class T> class List {
 public:
    typedef Iter<List<T> > MyIter;
    typedef int IterState;
 };
 List<int>::MyIter i;

Mututally-dependent class templates and recursive class templates
require pretty much the same kind of rules.  Instantiation must expand
templates in stages, with the first stage only expanding enough
members to determine the class' physical layout.

Jamshid Afshar
jamshid@emx.cc.utexas.edu