By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,234 Members | 2,075 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,234 IT Pros & Developers. It's quick & easy.

members in class template not inherited?

P: n/a
When I compile the following code:

//================================================== =
template <typename T>
class Foo {
public:
T x,y,z;
};

template <typename T>
class Bar : public Foo<T> {
public:
Bar<T>& operator+=(const Bar<T>& rhs) {
x += rhs.x;
y += rhs.y;
z += rhs.z;

return *this;
}
};
//================================================== =

I get the following message from gcc 3.4:

bad.cpp: In member function `Bar<T>& Bar<T>::operator+=(const Bar<T>&)':
bad.cpp:11: error: `x' undeclared (first use this function)
bad.cpp:11: error: (Each undeclared identifier is reported only once for
each function it appears in.)
bad.cpp:12: error: `y' undeclared (first use this function)
bad.cpp:13: error: `z' undeclared (first use this function)

If I "un-templatize" the classes Foo and Bar, the code compiles fine. Is
this a bug in gcc, or am I forgetting something about the way C++ handles
inheritance and templates?

Thanks,

Brett
Jul 22 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
wrote in news:op**************@aerow78f3043.lmtas.lmco.com in
comp.lang.c++:
When I compile the following code:

//================================================== =
template <typename T>
class Foo {
public:
T x,y,z;
};

template <typename T>
class Bar : public Foo<T> {
public:
Bar<T>& operator+=(const Bar<T>& rhs) {
x += rhs.x;
y += rhs.y;
z += rhs.z;

return *this;
}
};
//================================================== =

I get the following message from gcc 3.4:

bad.cpp: In member function `Bar<T>& Bar<T>::operator+=(const
Bar<T>&)': bad.cpp:11: error: `x' undeclared (first use this function)
bad.cpp:11: error: (Each undeclared identifier is reported only once
for each function it appears in.)
bad.cpp:12: error: `y' undeclared (first use this function)
bad.cpp:13: error: `z' undeclared (first use this function)

If I "un-templatize" the classes Foo and Bar, the code compiles fine.
Is this a bug in gcc, or am I forgetting something about the way C++
handles inheritance and templates?


It is not inheritance and templates, it si names that *depend* on a
template paramiter, because of specialization, whatever Foo< T > is
*depends* on T, so the compiler can't assume that Foo< T > is the
un-specialized version its already seen, so it can't assume x, y
and z are members of Foo< T >.

Ehat to do:

1) use this->x etc.

2) use explicit qualification:

Foo<T>::x += rhs.x;

Note that rhs.Foo<T>::x isn't required as its effectively (1).

3) use a using statement:

template <typename T>
class Bar : public Foo<T> {
public:

using Foo< T >::x;
using Foo< T >::y;
using Foo< T >::z;
Bar<T>& operator+=(const Bar<T>& rhs) {
x += rhs.x;
y += rhs.y;
z += rhs.z;

return *this;
}
};

HTH.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #2

P: n/a
no***@dummy.net wrote:
When I compile the following code:

//================================================== =
template <typename T>
class Foo {
public:
T x,y,z;
};

template <typename T>
class Bar : public Foo<T> {
public:
Bar<T>& operator+=(const Bar<T>& rhs) {
x += rhs.x;
y += rhs.y;
z += rhs.z;

return *this;
}
};
//================================================== =

I get the following message from gcc 3.4:

bad.cpp: In member function `Bar<T>& Bar<T>::operator+=(const Bar<T>&)':
bad.cpp:11: error: `x' undeclared (first use this function)
bad.cpp:11: error: (Each undeclared identifier is reported only once
for each function it appears in.)
bad.cpp:12: error: `y' undeclared (first use this function)
bad.cpp:13: error: `z' undeclared (first use this function)

If I "un-templatize" the classes Foo and Bar, the code compiles fine.
Is this a bug in gcc, or am I forgetting something about the way C++
handles inheritance and templates?


I think the problem is in name lookup rules. I am too lazy and too busy
to search through the Standard at this point, but try this fix:

Bar<T>& operator+=(const Bar<T>& rhs) {
this->x += rhs.x;
this->y += rhs.y;
this->z += rhs.z;

return *this;
}

Victor
Jul 22 '05 #3

P: n/a

<no***@dummy.net> wrote in message
news:op**************@aerow78f3043.lmtas.lmco.com. ..
When I compile the following code:

//================================================== =
template <typename T>
class Foo {
public:
T x,y,z;
};

template <typename T>
class Bar : public Foo<T> {
public:
Bar<T>& operator+=(const Bar<T>& rhs) {
x += rhs.x;
y += rhs.y;
z += rhs.z;

return *this;
}
};
//================================================== =

I get the following message from gcc 3.4:

bad.cpp: In member function `Bar<T>& Bar<T>::operator+=(const Bar<T>&)':
bad.cpp:11: error: `x' undeclared (first use this function)
bad.cpp:11: error: (Each undeclared identifier is reported only once for
each function it appears in.)
bad.cpp:12: error: `y' undeclared (first use this function)
bad.cpp:13: error: `z' undeclared (first use this function)

If I "un-templatize" the classes Foo and Bar, the code compiles fine. Is
this a bug in gcc, or am I forgetting something about the way C++ handles
inheritance and templates?


The latter. This is known as dependent name lookup.

From the standard 'In the definition of a class template ..., if the base
class of the class template depends upon a template parameter, the base
clsas scope is not examined during unqualified name lookup'. (section 14.6.2
para 3)

Why? I'm not sure. I'm sure there is a good reason.

The solution is to turn your unqualifed names into qualified names by
putting this-> in front of them.

this->x += rhs.x;

john
Jul 22 '05 #4

P: n/a
"John Harrison" <jo*************@hotmail.com> wrote in message
news:op**************@aerow78f3043.lmtas.lmco.com. ..
template <typename T>
class Bar : public Foo<T> {
public:
Bar<T>& operator+=(const Bar<T>& rhs) {
x += rhs.x;
y += rhs.y;
z += rhs.z;

return *this;
}
};

From the standard 'In the definition of a class template ..., if the base
class of the class template depends upon a template parameter, the base
clsas scope is not examined during unqualified name lookup'. (section 14.6.2
para 3)

Why? I'm not sure. I'm sure there is a good reason.
The reason I was given is that Foo<T> may be specialized so that it
does not have members 'x', 'y', and/or 'z'. It does not seem very
convicing to me, because the errors could spew forth when we finally
instantiate a faulty Bar<T> such as Bar<int>. Or maybe I'm missing
something.
The solution is to turn your unqualifed names into qualified names by
putting this-> in front of them.

this->x += rhs.x;


One can also say

Foo<T>::x += rhs.x;

For functions this could be dangerous as it turns off the virtual
function mechanism (ie. functions will be resolved statically). But I
prefer the "this->" way of doing it.
Jul 22 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.