Templates and accessing inherited members

Discussion in 'C++' started by Simon White, Jun 16, 2004.

  1. Simon White

    Simon White Guest

    Hi,

    I have code that looks legal to me and has compiled for years and on
    latest VC, etc compilers. Just recently gcc made a change to their
    compiler (3.4) that broke it. I don't have access to the C++ standard
    but information we do have access to uptill now suggests that this
    shouldn't be a problem. A code example is this:

    template<class T>
    class Base
    {
    protected:
    T* a;
    };

    template<class T>
    class Child: public Base<T>
    {
    public:
    Child() { a = 0; }
    };

    When compiled gcc 3.4 now complains that "a" is undefined as it nolonger
    looks to the base class(es). By default it now looks only to its own
    class scope or global scope. It now means you have to add either "using
    Base<T> a" to the child class or change occurances to use this->a.

    Is this behaviour correct and just wondered what reasoning there was
    behind it, especially when making the behaviour inconsistant after so
    long with normal structs and classes, requring large amounts of code rework?

    Regards,
    Simon
     
    Simon White, Jun 16, 2004
    #1
    1. Advertising

  2. "Simon White" <> wrote in message
    news:RGSzc.11$...
    > Hi,
    >
    > I have code that looks legal to me and has compiled for years and on
    > latest VC, etc compilers. Just recently gcc made a change to their
    > compiler (3.4) that broke it. I don't have access to the C++ standard
    > but information we do have access to uptill now suggests that this
    > shouldn't be a problem. A code example is this:
    >
    > template<class T>
    > class Base
    > {
    > protected:
    > T* a;
    > };
    >
    > template<class T>
    > class Child: public Base<T>
    > {
    > public:
    > Child() { a = 0; }
    > };
    >
    > When compiled gcc 3.4 now complains that "a" is undefined as it nolonger
    > looks to the base class(es). By default it now looks only to its own
    > class scope or global scope. It now means you have to add either "using
    > Base<T> a" to the child class or change occurances to use this->a.
    >
    > Is this behaviour correct and just wondered what reasoning there was
    > behind it, especially when making the behaviour inconsistant after so
    > long with normal structs and classes, requring large amounts of code

    rework?
    >


    Its correct, its called two phase lookup.

    The heart of the issue is that templates cannot be treated the same as
    normal structs and classes, because of the way the types of template
    parameters are not known when templates are first compiled, only when they
    are instantiated. Take your example

    template<class T>
    class Base
    {
    protected:
    T* a;
    };

    template<class T>
    class Child: public Base<T>
    {
    public:
    Child() { a = 0; }
    };

    Now you might think that it obvious that the a in Child::Child() must refer
    to Base::a but this isn't true at all. Suppose else where in your code you
    had this

    extern int a;

    template <>
    class Base<int>
    {
    };

    int f()
    {
    Child<int> x;
    }

    Base has been specialised with an int template parameter. The specialised
    version of Base does not have a member variable called a, but there is a
    global variable called a. In this code the a in Child::Child() would refer
    to the global variable a, so it is wrong for previous versions of gcc to
    assume that the a in Child::Child() refers to Base::a. And of course the
    compiler cannot (in general) know of the existence of this specialised
    version of Base when it is compiling Child.

    john
     
    John Harrison, Jun 16, 2004
    #2
    1. Advertising

  3. Simon White

    Sharad Kala Guest

    "Simon White" <> wrote in message
    news:RGSzc.11$...
    > Hi,
    >
    > I have code that looks legal to me and has compiled for years and on
    > latest VC, etc compilers. Just recently gcc made a change to their
    > compiler (3.4) that broke it. I don't have access to the C++ standard
    > but information we do have access to uptill now suggests that this
    > shouldn't be a problem. A code example is this:
    >
    > template<class T>
    > class Base
    > {
    > protected:
    > T* a;
    > };
    >
    > template<class T>
    > class Child: public Base<T>
    > {
    > public:
    > Child() { a = 0; }
    > };
    >
    > When compiled gcc 3.4 now complains that "a" is undefined as it nolonger
    > looks to the base class(es). By default it now looks only to its own
    > class scope or global scope. It now means you have to add either "using
    > Base<T> a" to the child class or change occurances to use this->a.
    >
    > Is this behaviour correct and just wondered what reasoning there was
    > behind it, especially when making the behaviour inconsistant after so
    > long with normal structs and classes, requring large amounts of code rework?


    Two phase name lookup strikes again!
    Since the name a is not dependent it will be looked up at the point where
    template is defined w/o taking into account the instantiation type(and not when
    being instantiated). Hence the error.
    Base<T>::a or this->a makes it a dependent name and hence name lookup is
    delayed.

    -Sharad
     
    Sharad Kala, Jun 16, 2004
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JKop
    Replies:
    3
    Views:
    521
  2. Dave
    Replies:
    3
    Views:
    385
    tom_usenet
    Aug 10, 2004
  3. lovecreatesbeauty
    Replies:
    43
    Views:
    1,322
    Keith Thompson
    Feb 6, 2006
  4. Mr Dyl
    Replies:
    2
    Views:
    507
    Mr Dyl
    Dec 1, 2005
  5. lovecreatesbeauty
    Replies:
    2
    Views:
    587
Loading...

Share This Page