Topic: virtual methods in class templates


Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/11/05
Raw View
efrank@upenn5.hep.upenn.edu (Ed Frank) writes:

 >Colleagues and I are having trouble reading the C++ '96 Working
 >paper.  We would like to know if class templates may have
 >virtual methods.

Yes, they may.

 >For example:
 >
 >        template <class T> X {
 >           virtual void method( void );
 >           T* _myT;
 >        }
 >
 >Is this a valid declaration?

Yes.

 >This question is aimed at elucidating
 >14.5.1.1 (item 1)  and 14.5.2 (item 3) in the Working Paper.

The code prohibited by 14.5.2/3  is this:

 class X {
  template <class T>
  virtual void method();
 };

Note the distinction between class templates with virtual methods
and classes with template virtual methods.

 >Next, we want to know about something related to scopes of
 >names.  If we have:
 >        template <class T> Base {
 >        protected:
 >           void baseMethod(void);   // not virtual
 >           T* _myT;
 >        }
 >and then derive
 >        template <class T> Deriv : public Base<T> {
 >           void derivedMethod( void );
 >        }
 >what is required for accessing _myT and void baseMethod(void) when
 >defining derivedMethod(void)?  For example, may we write
 >        template <class T>
 >        void
 >        Deriv<T>::derivedMethod( void ) {
 >           baseMethod();
 >           _myT = someTmaker();
 >        }

Yes, that's fine.

 >or must we write
 >        template <class T>
 >        void
 >        Deriv<T>::deriveMethod( void ) {
 >           this->baseMethod();
 >           this->_myT = someTmaker();
 >        }

That is of course fine too.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: dHarrison@worldnet.att.net (Doug Harrison)
Date: 1997/11/06
Raw View
On 05 Nov 97 17:00:36 GMT, efrank@upenn5.hep.upenn.edu (Ed Frank)
wrote:

(Note: I recently responded to this in comp.lang.c++.moderated, and
since it concerns questions I raised in comp.std.c++ a while back,
that failed to generate any discussion, I'm reposting the relevant
part of my reply here.)

>Next, we want to know about something related to scopes of
>names.  If we have:
>        template <class T> Base {
>        protected:
>           void baseMethod(void);   // not virtual
>           T* _myT;
>        }
>and then derive
>        template <class T> Deriv : public Base<T> {
>           void derivedMethod( void );
>        }
>what is required for accessing _myT and void baseMethod(void) when
>defining derivedMethod(void)?  For example, may we write
>        template <class T>
>        void
>        Deriv<T>::derivedMethod( void ) {
>           baseMethod();
>           _myT = someTmaker();
>        }
>or must we write
>        template <class T>
>        void
>        Deriv<T>::deriveMethod( void ) {
>           this->baseMethod();
>           this->_myT = someTmaker();
>        }

// begin old reply

Unfortunately, according to the Dec-96 draft, the latter is required,
because the scope of a base class that is dependent on a template
parameter isn't searched at template definition time, but only at
instantiation time. This causes all sorts of unintuitive binding
problems. For example, if you have a global function baseMethod,
that's visible from your derived class function, that's the one the
derived class calls, unless you qualify the call somehow. I posted
some questions about this recently in comp.std.c++, so please refer to
these messages for a more thorough discussion of this problem and
citations to the Dec-96 draft:

Newsgroups: comp.std.c++
Subject: Template name resolution
Date: Fri, 19 Sep 1997 07:25:40 GMT
Message-ID: <342a1400.40071660@netnews.worldnet.att.net>

Newsgroups: comp.std.c++
Subject: Re: Template name resolution
Date: Thu, 25 Sep 1997 01:45:35 GMT
Message-ID: <342bbc51.15559162@netnews.worldnet.att.net>

Both compilers I use, Visual C++ 5 and gcc 2.7.2, violate the draft,
because they do search dependent base classes. In the messages cited
above, I explained why I think this is proper in cases like the one
you presented, and why I think the draft took an example that was
really quite different and generalized it to include derivations for
which the rule is inappropriate. Unfortunately, I got no response at
all to either of those messages.

// end old reply

I got interested in this issue after reading this message:

Newsgroups: comp.lang.c++.moderated,comp.sys.hp.hpux
Subject: Global scope, base class scope, and templates
Date: 9 Sep 1997 21:13:59 -0400
Message-ID: <5v4s8f$gf8@netlab.cs.rpi.edu>

The poster described the above scenario, except that his function was
named "terminate", and his HP compiler called the global terminate,
per the draft standard. That message inspired only one reply, which
incorrectly (I think) concluded, without citing the draft, that his
compiler was in error. I think his compiler followed the draft to the
letter, straight into disaster.

--
Doug Harrison
dHarrison@worldnet.att.net
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: efrank@upenn5.hep.upenn.edu (Ed Frank)
Date: 1997/11/07
Raw View
In article <63qbcv$b3n@mulga.cs.mu.OZ.AU>, fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:

> The code prohibited by 14.5.2/3  is this:
>
>  class X {
>   template <class T>
>   virtual void method();
>  };
>
> Note the distinction between class templates with virtual methods
> and classes with template virtual methods.

Yes, I suspected that what you show in class X is what was being excluded.
What we got hung up on was:

  14.5.1.1  Member functions of class templates          [temp.mem.func]

1 A  member function of a class template is implicitly a member function
  template with the template-parameters of its  class  template  as  its
  template-parameters.

and then:

  14.5.2  Member templates                                    [temp.mem]

1 A template can be declared within a class or class  template;  such  a
  template  is  called  a  member  template.   A  member template can be
  defined within or outside its class definition or class template defi-
  nition. [...]
2 [omitted]
3 A  member function template shall not be virtual.  A specialization of
  a member function template does not override a virtual function from a
  base class.  [Example:  [omited]]


In the paragraphs above, 14.5.1.1, #1  seems to call methods in a class
template "member function templates" and then 14.5.2, #3 explicitly
forbids them from being virtual.  Is #3 in error and should have said
"member template" rather than "member _function_ template?"

 -Ed

Ed Frank
efrank@upenn5.hep.upenn.edu
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/11/07
Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) writes:

 >efrank@upenn5.hep.upenn.edu (Ed Frank) writes:
 >
 > >Next, we want to know about something related to scopes of
 > >names.  If we have:
 > >        template <class T> Base {
 > >        protected:
 > >           void baseMethod(void);   // not virtual
 > >           T* _myT;
 > >        }
 > >and then derive
 > >        template <class T> Deriv : public Base<T> {
 > >           void derivedMethod( void );
 > >        }
 > >what is required for accessing _myT and void baseMethod(void) when
 > >defining derivedMethod(void)?  For example, may we write
 > >        template <class T>
 > >        void
 > >        Deriv<T>::derivedMethod( void ) {
 > >           baseMethod();
 > >           _myT = someTmaker();
 > >        }
 >
 >Yes, that's fine.

Sorry, I was a bit quick off the mark here -- I hadn't considered the
issue of dependent names.  A closer examination of the draft suggests
that baseMethod() is *not* a dependent name according to 14.6.2,
and so 14.6/9 applies:

 "If a name does not depend on a template-parameter (as defined
 in 14.6.2), a declaration (or set of declarations) for that
 name shall be in scope at the point where the name appears in
 the template definition; ..."

The wording is not entirely clear, but the intent appears to be that
this example is ill-formed, because the base class scope is not examined
(14.6.2/3).

 > >or must we write
 > >        template <class T>
 > >        void
 > >        Deriv<T>::deriveMethod( void ) {
 > >           this->baseMethod();
 > >           this->_myT = someTmaker();
 > >        }

Yes, I think you need to do that.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: efrank@upenn5.hep.upenn.edu (Ed Frank)
Date: 1997/11/05
Raw View
Colleagues and I are having trouble reading the C++ '96 Working
paper.  We would like to know if class templates may have
virtual methods.  For example:

        template <class T> X {
           virtual void method( void );
           T* _myT;
        }

Is this a valid declaration?  This question is aimed at elucidating
14.5.1.1 (item 1)  and 14.5.2 (item 3) in the Working Paper.

Next, we want to know about something related to scopes of
names.  If we have:
        template <class T> Base {
        protected:
           void baseMethod(void);   // not virtual
           T* _myT;
        }
and then derive
        template <class T> Deriv : public Base<T> {
           void derivedMethod( void );
        }
what is required for accessing _myT and void baseMethod(void) when
defining derivedMethod(void)?  For example, may we write
        template <class T>
        void
        Deriv<T>::derivedMethod( void ) {
           baseMethod();
           _myT = someTmaker();
        }
or must we write
        template <class T>
        void
        Deriv<T>::deriveMethod( void ) {
           this->baseMethod();
           this->_myT = someTmaker();
        }

Thanks,

        -Ed


[Was posted to comp.lang.c++ recently, but had no replies, perhaps because
comp.std.c++ is more appropriate]
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]