Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Inheritance from a Template class, problems accessing protected member

302 views
Skip to first unread message

liam_herron

unread,
Sep 5, 2008, 9:21:55 AM9/5/08
to

Here is my code:

#include <iostream>

template<typename T>
class RawPtr
{
protected:
T* pointee_;

public:
RawPtr() : pointee_(0) {}
RawPtr(T* pT) : pointee_(pT) {}
};


template<typename T>
class SmartPtr : public RawPtr<T>
{
public:
SmartPtr() : RawPtr<T>() {}
explicit SmartPtr(T* pT) : RawPtr<T>(pT)
{
if (pointee_ != 0)
{
std::cout << "SmartPtr(T* pT): pointee_ non-null." <<
std::endl;
}
}

};


int main()
{
double *pDoubleRaw = new double(1.0);
SmartPtr<double> pDouble(pDoubleRaw);
return 0;
}


On Linux (g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-3)) I get the
following compilation error:

g++ testInheritanceWithTemplates.cpp
testInheritanceWithTemplates.cpp: In constructor
`SmartPtr<T>::SmartPtr(T*)':
testInheritanceWithTemplates.cpp:27: error: `pointee_' was not
declared in this scope


On Windows, this compiles fine.

Any ideas why this doesn't work on Linux? Does the C++ standard think
that this is legal?

Regards,
Liam Herron

cch@srdgame

unread,
Sep 5, 2008, 11:10:17 AM9/5/08
to
于 Fri, 05 Sep 2008 06:21:55 -0700,liam_herron写到:


hi

Following is the code I tested.

#include <iostream>

template<typename T>
class RawPtr
{
protected:
T* pointee_;

public:
RawPtr() : pointee_(0) {}
RawPtr(T* pT) : pointee_(pT) {}
};


template<typename T>
class SmartPtr : public RawPtr<T>
{
public:
SmartPtr() : RawPtr<T>() {}
explicit SmartPtr(T* pT) : RawPtr<T>(pT)
{

if (RawPtr<T>::pointee_ != 0)


{
std::cout << "SmartPtr(T* pT): pointee_ non-null." <<
std::endl;
}
}

};

int main()
{
int n = 10;
SmartPtr<int> IntPtr(&n);
}

--
cch@srdgame

liam_herron

unread,
Sep 5, 2008, 1:10:04 PM9/5/08
to
Yeah, I was able to do that as well but I am not sure where in the
standard it requires to specify the scope
of a templated parent class (Remember this is not the case for non-
templated inheritance).

If anyone can point me to where this is in the 2003 C++ standard, that
would be great.

Regards,
Liam

Jim Z. Shi

unread,
Sep 8, 2008, 10:44:21 PM9/8/08
to

liam_herron wrote:
>
> Here is my code:
>
> #include <iostream>
>
>
>
> template<typename T>
> class RawPtr
> {
> protected:
> T* pointee_;
>
> public:
> RawPtr() : pointee_(0) {}
> RawPtr(T* pT) : pointee_(pT) {}
> };
>
>
> template<typename T>
> class SmartPtr : public RawPtr<T>

when the compiler gets here, it will encounter a name `RawPtr<T>', and
knows that that is a template class of type<T>. when a class is
inherited from a template class, compiler will *only* find the template
base class *name* in his symbol table, and will not check its definition
detail.


> {
> public:
> SmartPtr() : RawPtr<T>() {}
> explicit SmartPtr(T* pT) : RawPtr<T>(pT)
> {
> if (pointee_ != 0)

The reason of your original code is the template specialization. when
you're defining your SmartPtr<T> here, compiler only know his base
template class name but not his details, so compiler doesn't know
SmartPtr<T> has a member pointee_ inherited from RawPtr<T>. But you
could explicitly point that out using:
if(this->pointee_ != 0)
or
if(RawPtr<T>::pointee_ != 0)
this will tell the compiler that there is a implicit rule that RawPtr<T>
has to contain a member named pointee_, and this rule will be checked
when you instantiate a SmartPtr<T> object.


> {
> std::cout << "SmartPtr(T* pT): pointee_ non-null." <<
> std::endl;
> }
> }
>
> };
>
>
> int main()
> {
> double *pDoubleRaw = new double(1.0);
> SmartPtr<double> pDouble(pDoubleRaw);
> return 0;
> }
>
>
> On Linux (g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-3)) I get the
> following compilation error:
>
> g++ testInheritanceWithTemplates.cpp
> testInheritanceWithTemplates.cpp: In constructor
> `SmartPtr<T>::SmartPtr(T*)':
> testInheritanceWithTemplates.cpp:27: error: `pointee_' was not
> declared in this scope
>
>
> On Windows, this compiles fine.
>
> Any ideas why this doesn't work on Linux? Does the C++ standard think
> that this is legal?
>
> Regards,
> Liam Herron

what g++ has done here is right. because of template specialization,
compiler will not guarantee anything at complier time. think about this:

template<typename T> class base;

template<> class base<int>
{
protected:
int i;
};
template<> class base<double>
{
protected:
double foo()
{
return .0;
}
};

template<typename T>
class derived : public base<T>
{
int bar()
{
//i; is there `i'?
//foo(); or is there a foo()?
return 0;
}

};

in derived<T>::bar(), what should the compiler guarantee you? a `i' or
`foo()', or even something else? -- nothing is good, so just guarantee
nothing here. you should cry for what you want exactly and compiler will
check it for you when it instantiates that.

cheers & HTH,
Jim

0 new messages