accessing members of a templated base class

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Simon Saunders

    #16
    Re: accessing members of a templated base class

    On Sun, 10 Aug 2003 14:13:59 +0100, John Harrison wrote:
    [color=blue]
    > This code fails to compile on Comeau C++ and VC++ 7.1 (with language
    > extensions disabled)
    >
    > template <class T>
    > struct B
    > {
    > T b;
    > };
    >
    > template <class T>
    > struct D : B<T>
    > {
    > void f() { b = 1; }
    > };
    >
    > int main()
    > {
    > D<int> x;
    > x.f();
    > }
    >
    > Error messages refer to 'b = 1;' with the message 'undefined identifier b'.
    > Substituting this->b for b or making B a non-template class both make the
    > code compile.
    >
    > What's going on here? I was so surprised when I saw this on VC++ that I
    > assumed it was a compiler bug, but apparently not.
    >
    > john[/color]

    It's definitely not a compiler bug. HP's aCC compiler even tells you where
    to look in the Standard:

    Error (future) 641: "xx.cc", line 16 # Undeclared variable 'b'. A variable
    with the same name exists in a template base class, but is not visible
    according to the Standard lookup rules (See [temp.dep], 14.6.2(3) in the
    C++ Standard). You can make it visible by writing 'this->b'.
    void f() { b = 3; }
    ^

    There is an explanation of this rule in the book "C++ Templates - The
    Complete Guide" by Vandevoorde and Josuttis (section 9.4.2).

    Comment

    • Pete Becker

      #17
      Re: accessing members of a templated base class

      Pete Becker wrote:[color=blue]
      >
      > "Alf P. Steinbach" wrote:[color=green]
      > >
      > > If Visual C++ 7.1 also uses the EDG front-end then it's just one.[/color]
      >
      > Visual C++ 7.1 does not use the EDG front end.[/color]

      What I should have said is, do you have any reason to think that VC++
      used EDG's front end? I have no information either way.

      --

      Pete Becker
      Dinkumware, Ltd. (http://www.dinkumware.com)

      Comment

      • Alf P. Steinbach

        #18
        Re: accessing members of a templated base class

        On Sun, 10 Aug 2003 10:12:08 -0400, Pete Becker <petebecker@acm .org> wrote:
        [color=blue]
        >"Alf P. Steinbach" wrote:[color=green]
        >>
        >> Am I glad that I haven't even checked whether I _have_ VC 7.1... ;-)[/color]
        >
        >Are you also glad that you haven't checked whether you have the EDG
        >front end? <g> It rejects this code, too.
        >[color=green]
        >>
        >> It compiles just fine with 7.0, with and without language extensions
        >> disabled (/Za).
        >>[color=darkred]
        >> >What's going on here? I was so surprised when I saw this on VC++ that I
        >> >assumed it was a compiler bug, but apparently not.[/color]
        >>
        >> Apparently it is a compiler bug.
        >>
        >> At least, I agree with Victor that the usual look-up rules should apply.[/color]
        >
        >Since EDG rejects it, I suspect that the analysis is wrong. I don't
        >claim to understand two-phase lookup, but it looks to me like 'b' is a
        >dependent name. After all, its meaning depends on the defintion of B<T>,
        >and B<T> can be specialized for various T's. During phase one it has to
        >be explicitly qualified, in order to tell the compiler that not having a
        >'b' in B<T> is an error.[/color]

        ?

        I agree that this two-phase thing is a mess... ;-) But just reading the
        standard it says that such names are "unbound" (including the operator)
        and become bound at template instantiation time. So I fail to see why
        it even _could_ be correct to fail to compile this code; all the
        information the compiler needs is there, when it needs it.


        PS: I also don't understand "that not having a 'b' in B<T> is an error".

        Comment

        • Pete Becker

          #19
          Re: accessing members of a templated base class

          "Alf P. Steinbach" wrote:[color=blue]
          >
          > PS: I also don't understand "that not having a 'b' in B<T> is an error".[/color]

          If D<T> mentions 'this->b' but doesn't define 'b' then 'b' must be
          defined in its base. If B<int> doesn't have a member named 'b' then the
          name is undefined.

          --

          Pete Becker
          Dinkumware, Ltd. (http://www.dinkumware.com)

          Comment

          • Pete Becker

            #20
            Re: accessing members of a templated base class

            "Alf P. Steinbach" wrote:[color=blue]
            >
            > On Sun, 10 Aug 2003 10:12:08 -0400, Pete Becker <petebecker@acm .org> wrote:
            >[color=green]
            > >Since EDG rejects it, I suspect that the analysis is wrong. I don't
            > >claim to understand two-phase lookup, but it looks to me like 'b' is a
            > >dependent name. After all, its meaning depends on the defintion of B<T>,
            > >and B<T> can be specialized for various T's. During phase one it has to
            > >be explicitly qualified, in order to tell the compiler that not having a
            > >'b' in B<T> is an error.[/color]
            >
            > ?
            >
            > I agree that this two-phase thing is a mess... ;-) But just reading the
            > standard it says that such names are "unbound" (including the operator)
            > and become bound at template instantiation time. So I fail to see why
            > it even _could_ be correct to fail to compile this code; all the
            > information the compiler needs is there, when it needs it.
            >[/color]

            In this area I defer to EDG's reading of the standard.

            --

            Pete Becker
            Dinkumware, Ltd. (http://www.dinkumware.com)

            Comment

            • Alf P. Steinbach

              #21
              Re: accessing members of a templated base class

              On Sun, 10 Aug 2003 16:10:53 +0100, "Simon Saunders" <simon.saunders @net.ntl.com> wrote:
              [color=blue]
              >On Sun, 10 Aug 2003 14:13:59 +0100, John Harrison wrote:
              >[color=green]
              >> This code fails to compile on Comeau C++ and VC++ 7.1 (with language
              >> extensions disabled)
              >>
              >> template <class T>
              >> struct B
              >> {
              >> T b;
              >> };
              >>
              >> template <class T>
              >> struct D : B<T>
              >> {
              >> void f() { b = 1; }
              >> };
              >>
              >> int main()
              >> {
              >> D<int> x;
              >> x.f();
              >> }
              >>
              >> Error messages refer to 'b = 1;' with the message 'undefined identifier b'.
              >> Substituting this->b for b or making B a non-template class both make the
              >> code compile.
              >>
              >> What's going on here? I was so surprised when I saw this on VC++ that I
              >> assumed it was a compiler bug, but apparently not.
              >>
              >> john[/color]
              >
              >It's definitely not a compiler bug.[/color]

              How can you be sure of that?

              [color=blue]
              >HP's aCC compiler even tells you where
              >to look in the Standard:
              >
              >Error (future) 641: "xx.cc", line 16 # Undeclared variable 'b'. A variable
              > with the same name exists in a template base class, but is not visible
              > according to the Standard lookup rules (See [temp.dep], 14.6.2(3) in the
              > C++ Standard). You can make it visible by writing 'this->b'.
              > void f() { b = 3; }
              > ^[/color]

              According to §14.6.2/3 the base class scope is not examined _until_ the class
              is instantiated -- naturally, since the information required (type T) isn't
              present until then. And until then, 'b' is "unbound" according to §14.6.2/1.


              [color=blue]
              >There is an explanation of this rule in the book "C++ Templates - The
              >Complete Guide" by Vandevoorde and Josuttis (section 9.4.2).[/color]

              Could you please quote? The rule about not examining the base class
              scope until instantiation needs no explanation, really, so if that's
              what Jousittis explains it's irrelevant. The failure to compile this
              code sans name qualification does need an explanation, and the effect
              of qualification (on these compilers) needs to be rooted in the standard.

              Comment

              • Alf P. Steinbach

                #22
                Re: accessing members of a templated base class

                On Sun, 10 Aug 2003 11:22:29 -0400, Pete Becker <petebecker@acm .org> wrote:
                [color=blue]
                >Pete Becker wrote:[color=green]
                >>
                >> "Alf P. Steinbach" wrote:[color=darkred]
                >> >
                >> > If Visual C++ 7.1 also uses the EDG front-end then it's just one.[/color]
                >>
                >> Visual C++ 7.1 does not use the EDG front end.[/color]
                >
                >What I should have said is, do you have any reason to think that VC++
                >used EDG's front end? I have no information either way.[/color]

                Neither have I; if was an "if".

                Comment

                • Alf P. Steinbach

                  #23
                  Re: accessing members of a templated base class

                  On Sun, 10 Aug 2003 17:27:47 +0100, "Simon Saunders" <simon.saunders @net.ntl.com> wrote:
                  [color=blue]
                  >On Sun, 10 Aug 2003 15:41:25 +0000, Alf P. Steinbach wrote:
                  >[color=green]
                  >> On Sun, 10 Aug 2003 16:10:53 +0100, "Simon Saunders"
                  >> <simon.saunders @net.ntl.com> wrote:
                  >>[color=darkred]
                  >>>On Sun, 10 Aug 2003 14:13:59 +0100, John Harrison wrote:
                  >>>
                  >>>> This code fails to compile on Comeau C++ and VC++ 7.1 (with language
                  >>>> extensions disabled)
                  >>>>
                  >>>> template <class T>
                  >>>> struct B
                  >>>> {
                  >>>> T b;
                  >>>> };
                  >>>>
                  >>>> template <class T>
                  >>>> struct D : B<T>
                  >>>> {
                  >>>> void f() { b = 1; }
                  >>>> };
                  >>>>
                  >>>> int main()
                  >>>> {
                  >>>> D<int> x;
                  >>>> x.f();
                  >>>> }
                  >>>> }
                  >>>> Error messages refer to 'b = 1;' with the message 'undefined
                  >>>> identifier b'. Substituting this->b for b or making B a non-template
                  >>>> class both make the code compile.
                  >>>>
                  >>>> What's going on here? I was so surprised when I saw this on VC++ that
                  >>>> I assumed it was a compiler bug, but apparently not.
                  >>>>
                  >>>> john
                  >>>
                  >>>It's definitely not a compiler bug.[/color]
                  >>
                  >> How can you be sure of that?
                  >>
                  >>[color=darkred]
                  >>>HP's aCC compiler even tells you where to look in the Standard:
                  >>>
                  >>>Error (future) 641: "xx.cc", line 16 # Undeclared variable 'b'. A
                  >>>variable
                  >>> with the same name exists in a template base class, but is not
                  >>> visible according to the Standard lookup rules (See [temp.dep],
                  >>> 14.6.2(3) in the C++ Standard). You can make it visible by writing
                  >>> 'this->b'.
                  >>> void f() { b = 3; }
                  >>> ^[/color]
                  >>
                  >> According to §14.6.2/3 the base class scope is not examined _until_ the
                  >> class is instantiated -- naturally, since the information required
                  >> (type T) isn't present until then. And until then, 'b' is "unbound"
                  >> according to §14.6.2/1.
                  >>
                  >>
                  >>[/color]
                  >
                  >14.6.2/1 says that _dependent_ names are unbound until instantiation. The
                  >point is that the name "b" in the definition of D<T>::f() is a
                  >nondependent name according to the rules laid out in the Standard (whereas
                  >"this->b" is dependent).[/color]

                  Ah, this is opposite of Pete Becker's tentative usage of the term.

                  The wording of the standard just become much clearer... ;-)

                  Although the effect it specifies is counter-intuitive in the extreme;
                  awkward and inconsistent name lookup, so incomprehensibl e that neither I,
                  Victor Bazarow nor Pete Becker have fully grasped it, just to marginally
                  optimize compilation. Donald Knuth was right. It's evil.

                  [color=blue]
                  >...
                  >I'll do my best to summarize it. Nondependent names are looked up when the
                  >template D is first encountered, not postponed until instantiation as is
                  >the case for dependent names. The advantage of this approach is that
                  >errors caused by missing symbols can be diagnosed earlier. It also
                  >prevents surprises resulting from explicit specializations of the
                  >dependent base class, e.g. consider this:
                  >
                  >#include <iostream>
                  >
                  >using namespace std;
                  >
                  >int b = 0;
                  >
                  >template <class T>
                  >struct B
                  >{
                  > T b;
                  >};
                  >
                  >template <class T>
                  >struct D : B<T>
                  >{
                  > void f() { b = 3; }
                  >};
                  >
                  >template <>
                  >struct B<int>
                  >{
                  >};
                  >
                  >int main()
                  >{
                  > D<int> x;
                  > x.f();
                  > cout<<b<<endl;
                  >}
                  >
                  >Older compilers (such as Visual C++ 6.0) that do not implement the current
                  >rules will compile this and print out "3" when the program is executed,[/color]

                  Isn't that right according to current rules? 'b' in D is, counter-intuitively
                  and inconsistent with non-template code, bound to the global 'b'?

                  [color=blue]
                  >yet without the explicit specialization the output is "0".[/color]

                  ?

                  Comment

                  • Pete Becker

                    #24
                    Re: accessing members of a templated base class

                    "Alf P. Steinbach" wrote:[color=blue]
                    >
                    > Although the effect it specifies is counter-intuitive in the extreme;
                    > awkward and inconsistent name lookup, so incomprehensibl e that neither I,
                    > Victor Bazarow nor Pete Becker have fully grasped it[/color]

                    I haven't tried to, so that's not a meaningful data point.

                    --

                    Pete Becker
                    Dinkumware, Ltd. (http://www.dinkumware.com)

                    Comment

                    • Alf P. Steinbach

                      #25
                      Re: accessing members of a templated base class

                      On Sun, 10 Aug 2003 13:51:17 -0400, Pete Becker <petebecker@acm .org> wrote:
                      [color=blue]
                      >"Alf P. Steinbach" wrote:[color=green]
                      >>
                      >> Although the effect it specifies is counter-intuitive in the extreme;
                      >> awkward and inconsistent name lookup, so incomprehensibl e that neither I,
                      >> Victor Bazarow nor Pete Becker have fully grasped it[/color]
                      >
                      >I haven't tried to, so that's not a meaningful data point.[/color]

                      You have years of experience with C++, you're a smart guy, and you work
                      at Dinkumware.

                      IMO language should not be so complicated that you (or I, for that matter)
                      has to really try; with a few years of usage it should all be there, although
                      I do not require the same of C++ as of Pascal, which I and I think most
                      real programmers at that time knew the full syntax & semantics of in detail.

                      Comment

                      • Pete Becker

                        #26
                        Re: accessing members of a templated base class

                        "Alf P. Steinbach" wrote:[color=blue]
                        >
                        > On Sun, 10 Aug 2003 13:51:17 -0400, Pete Becker <petebecker@acm .org> wrote:
                        >[color=green]
                        > >"Alf P. Steinbach" wrote:[color=darkred]
                        > >>
                        > >> Although the effect it specifies is counter-intuitive in the extreme;
                        > >> awkward and inconsistent name lookup, so incomprehensibl e that neither I,
                        > >> Victor Bazarow nor Pete Becker have fully grasped it[/color]
                        > >
                        > >I haven't tried to, so that's not a meaningful data point.[/color]
                        >
                        > You have years of experience with C++, you're a smart guy, and you work
                        > at Dinkumware.[/color]

                        None of which give me any significant experience with the details of
                        two-phase lookup. I haven't studied it, so the fact that I don't
                        understand it says very little about its comprehensibili ty. Like most
                        powerful tools, programming languages require study and practice.

                        --

                        Pete Becker
                        Dinkumware, Ltd. (http://www.dinkumware.com)

                        Comment

                        Working...