Topic: Rationale for "this->" in template derived classes?


Author: pjl.removethis@removethistoo.mac.com ("Paul J. Lucas")
Date: Thu, 22 Apr 2004 19:05:59 +0000 (UTC)
Raw View
 In reading over the changes to g++ 3.4.0, I came across the
 example below.  Can somebody explain why this is in the C++
 standard (presumeably, since g++ purports to implement the
 standard)?

 Why are the rules for template classes different from ordinary
 classes?

 - Paul

 From <http://gcc.gnu.org/gcc-3.4/changes.html>, C++ section,
 4th bullet:

In a template definition, unqualified names will no longer find members of a
dependent base. For example,

        template <typename T> struct B {
          int m;
          int n;
          int f ();
          int g ();
        };
        int n;
        int g ();
        template <typename T> struct C : B<T> {
          void g ()
          {
            m = 0; // error
            f ();  // error
            n = 0; // ::n is modified
            g ();  // ::g is called
          }
        };


You must make the names dependent by prefixing them with this->. Here is the
corrected definition of C<T>::g,

        template <typename T> void C<T>::g ()
        {
          this->m = 0;
          this->f ();
          this->n = 0
          this->g ();
        }

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rogero@howzatt.demon.co.uk ("Roger Orr")
Date: Thu, 22 Apr 2004 23:38:47 +0000 (UTC)
Raw View
""Paul J. Lucas"" <pjl.removethis@removethistoo.mac.com> wrote in message
news:1nShc.54253$xn6.9864@newssvr25.news.prodigy.com...
> In reading over the changes to g++ 3.4.0, I came across the
> example below.  Can somebody explain why this is in the C++
> standard (presumeably, since g++ purports to implement the
> standard)?
>
> Why are the rules for template classes different from ordinary
> classes?

The idea is to avoid surprises.  The difficulty with templated base classes
is that the template could be explicitly specialized.

For an example, see "C++ Templates The Complete Guide" by Josuttis and
Vandevoorde p137:

HTH,
Roger Orr
--
MVP in C++ at www.brainbench.com


---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Fri, 23 Apr 2004 04:52:44 +0000 (UTC)
Raw View
pjl.removethis@removethistoo.mac.com ("Paul J. Lucas") writes:

>  In reading over the changes to g++ 3.4.0, I came across the
>  example below.  Can somebody explain why this is in the C++
>  standard (presumeably, since g++ purports to implement the
>  standard)?

g++ does *not* purport to implement the standard. It purports to get
    very much closer with each release. :-) Amoung other things, they
    do not claim to implement export.

>  Why are the rules for template classes different from ordinary
>  classes?

You can find the reasoning behind the decision in D&E, 15.10.2 .
    Alternatively, I made an attempt to explain some facets of the
    situation a few days ago : http://xrl.us/bxe3 in a thread on
    comp.lang.c++.moderated, but I'm not really an expert. :-)
>
>  - Paul
>
>  From <http://gcc.gnu.org/gcc-3.4/changes.html>, C++ section,
>  4th bullet:
>
> In a template definition, unqualified names will no longer find members of a
> dependent base. For example,
>
>         template <typename T> struct B {
>           int m;
>           int n;
>           int f ();
>           int g ();
>         };
>         int n;
>         int g ();
>         template <typename T> struct C : B<T> {

Since template specialization allows different specializations of B
    to have different members, depenending on T, it is not possible
    to look up member names in B<T> until T is known. T is not known
    when the definition is compiled; it is decided at the point of
    instantiation. But postponing name lookup until the point of
    instantiation has several problems:

    (a) Certain classes of errors are not dectable. Ever see template
        code which is wrong, but 'compiles' anyway, simply because
        the template is never instantiated with the right parameters?
        I have.

    (b) It provides no language-supported way to enforce seperation
        between interface and implementation (this is the facet I
        explain in the link above).

So C++ has a notion of 'dependent name', which is rigorously defined
    in 14.6.2.

But looking up names in depenendent base classes would make all names
    depenendent, which would eliminate the value of such a notion.


>           void g ()
>           {
>             m = 0; // error
>             f ();  // error
>             n = 0; // ::n is modified
>             g ();  // ::g is called

The standard defines dependent names in 14.6.2 . AFAICT, none of
    these qualify as dependent names.

>           }
>         };
>
>
> You must make the names dependent by prefixing them with this->. Here is the
> corrected definition of C<T>::g,
>
>         template <typename T> void C<T>::g ()
>         {
>           this->m = 0;
>           this->f ();
>           this->n = 0
>           this->g ();
>         }
[snip]

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]