Topic: Why do my templates not deduce their base class members?


Author: bill@gibbons.org (Bill Gibbons)
Date: Fri, 29 Mar 2002 10:46:29 GMT
Raw View
In article <a7vhdl$acv$1@news.wplus.spb.ru>, "Ruslan Abdikeev"
<ruslan_abdikeevREMOVE_IT@hotmail.com> wrote:

> "Solosnake" <solosnake@solosnake.without_this.freeserve.co.uk> wrote in
message
> news:a7ukt3$f09$2@newsg4.svr.pol.co.uk...
> > My compiler expects me to completely specify 'data_' usage as
> > 'Foo<T>::data_' in order to compile correctly, however in untemplated
> > classes it deduces that I am in fact using the 'data_' member of my base
> > class CFoo, even when I inherit from a Foo<float> it finds the correct
> > member variable. Is this behaviour correct? Evey usage of 'data_' now
> > becomes long and ugly. Why can I not expect a templated class to deduce
> > correctly its inherited members?
> >
> > template<typename T>
> > class Foo {
> >     protected:
> >         T    data_;
> >    };
> >
> > template<typename T>
> > class Bar : public Foo<T> {
> >     public:
> >         T get_data(void){return data_;} // Compiler
> > doesn't like this line.
> > Prefers 'T get_data(void){return Foo<T>::data_;}' Why?
> >     };
> >
>
> It is nothing to do with deduction.
> It's just the way a name lookup works.
>
> Your compiler is right (14.6.2/3), you should use Foo<T>::data_
> or this->data_, or any type-dependent form.
>
> Definition
>
>    T get_data(void) { return this->data_; }
>
> is fine as well: "this" is type-dependent on T (14.6.2.2/2),
> operator -> denotes type-dependent name (14.6.2/1),
> and, consequently, the expression "this->data_" is type-dependent.
> Dependent names are unbound and looked up at the point
> of instantiation (14.6.2/1), so everything is OK.
>
> As to your question, standard says (14.6.2/3):
> In the definition of a class template or in the definition of a member of such
> a template that appears outside of the template definition, if a base class
> of this template depends on a template-parameter, the base class scope
> is not examined during name lookup until the class template is instantiated.

And the reason for this is that for any given T and Bar<T> the actual Foo<T>
used as the base class may be a specialization in which the type of "data_"
is different or in which "data_" doesn't even exist.  So the names declared
in the template Foo are not necessarily relevant to the template Bar and must
not be considered in name lookup at template declaration time.

Since templates must distinguish type-dependent from non-type-dependent names
at template declaration time and the unqualified name "data_" does not match
a member of Bar, it must be considered non-type-dependent and so will be
looked up at the point of template declaration, not at the point of
instantiation.  So it cannot match a name in "Foo" at all.


-- Bill Gibbons

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Solosnake" <solosnake@solosnake.without_this.freeserve.co.uk>
Date: Thu, 28 Mar 2002 15:27:37 GMT
Raw View
Hello

My compiler expects me to completely specify 'data_' usage as
'Foo<T>::data_' in order to compile correctly, however in untemplated
classes it deduces that I am in fact using the 'data_' member of my base
class CFoo, even when I inherit from a Foo<float> it finds the correct
member variable. Is this behaviour correct? Evey usage of 'data_' now
becomes long and ugly. Why can I not expect a templated class to deduce
correctly its inherited members?

template<typename T>
class Foo {
    protected:
        T    data_;
   };

class CFoo {
    protected:
        float data_;
    };

template<typename T>
class Bar : public Foo<T> {
    public:
        T get_data(void){return data_;} // Compiler doesn't like this line.
Prefers 'T get_data(void){return Foo<T>::data_;}' Why?
    };

class CBar : public CFoo {
    public:
        float get_data(void){return data_;} // This works fine.
    };

class CFooBar : public Foo<float> {
    public:
        float get_data(void){return data_;} // Even this works fine.
    };

Thanks again,

D. Stockdale









---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Ruslan Abdikeev" <ruslan_abdikeevREMOVE_IT@hotmail.com>
Date: Thu, 28 Mar 2002 16:50:41 GMT
Raw View
"Solosnake" <solosnake@solosnake.without_this.freeserve.co.uk> wrote in message
news:a7ukt3$f09$2@newsg4.svr.pol.co.uk...
> My compiler expects me to completely specify 'data_' usage as
> 'Foo<T>::data_' in order to compile correctly, however in untemplated
> classes it deduces that I am in fact using the 'data_' member of my base
> class CFoo, even when I inherit from a Foo<float> it finds the correct
> member variable. Is this behaviour correct? Evey usage of 'data_' now
> becomes long and ugly. Why can I not expect a templated class to deduce
> correctly its inherited members?
>
> template<typename T>
> class Foo {
>     protected:
>         T    data_;
>    };
>
> template<typename T>
> class Bar : public Foo<T> {
>     public:
>         T get_data(void){return data_;} // Compiler
> doesn't like this line.
> Prefers 'T get_data(void){return Foo<T>::data_;}' Why?
>     };
>

It is nothing to do with deduction.
It's just the way a name lookup works.

Your compiler is right (14.6.2/3), you should use Foo<T>::data_
or this->data_, or any type-dependent form.

Definition

   T get_data(void) { return this->data_; }

is fine as well: "this" is type-dependent on T (14.6.2.2/2),
operator -> denotes type-dependent name (14.6.2/1),
and, consequently, the expression "this->data_" is type-dependent.
Dependent names are unbound and looked up at the point
of instantiation (14.6.2/1), so everything is OK.

As to your question, standard says (14.6.2/3):
In the definition of a class template or in the definition of a member of such
a template that appears outside of the template definition, if a base class
of this template depends on a template-parameter, the base class scope
is not examined during name lookup until the class template is instantiated.

Hope it makes things clearer,

Sincerely,

Ruslan Abdikeev
Brainbench MVP for Visual C++
http://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.research.att.com/~austern/csc/faq.html                ]