开发者

C++ template inheritance issue with base types

I have the following cod开发者_运维百科e and it fails to compile

template < typename T >
class Base
{
public:

    typedef T * TPtr;

    void func()
    {
    }
};

template < typename T >
class Derived : public Base< T >
{
public:
    using Base< T >::TPtr;
    using Base< T >::func;

    TPtr ptr;
};

int main( int c, char *v[] )
{
    Derived< int > d;
    d.func();
}

The compiler issues the following.

t.cpp:16: error: 'TPtr' does not name a type
t.cpp:16: note: (perhaps 'typename Base<T>::TPtr' was intended)

Now I know I could simply do as the compiler is suggesting but I can't understand why the

    using Base< T >::TPtr;

doesn't work.

If I comment out the "TPtr ptr" line then it compiles, proving that the "using Base< T >::func;" statement works.

Any ideas?


Base< T >::TPtr is a so-called dependent name so you need to prefix it with typename to make the declaration work.

Additionally, using doesn’t work with typename so you need to use a typedef instead:

typedef typename Base<T>::TPtr TPtr;

The issue is that the compiler can’t decide – without knowing what T is! – whether TPtr in this context names a type or a variable/function. To avoid ambiguities, it always assumes the latter, unless explicitly told otherwise (hence the need for typename).


This is part of a defect. While C++03 did provide using typename, it did not provide the necessary rules to say that the name declared by the using declaration is a type-name. It just provided the instrument to say that the name referenced in the using declaration is a type-name. So you can do in fact the following, but with varying success among compilers. Some will make it work, but some won't.

template < typename T >
class Derived : public Base< T >
{
public:
    using typename Base< T >::TPtr;
    using Base< T >::func;
      // up to here it's alright
    TPtr ptr;
      // but this may only work on some compilers
};

This issue has been fixed for C++0x. For C++03, the way to work around it is to use a typedef instead.


I can't understand why the:
using Base< T >::TPtr;
doesn't work.

Due to possible template specialization, Base< T >::TPtr can be anything: a type name, variable name, function, etc.

With the keyword typename you tell compiler that it can be a type name only.

Here is a decent explanation of what sort of ambiguities it serves to resolve. Scroll down to "The Problem", it covers your case precisely.


When you write TPtr ptr;

it is seen as Base<T>::TPtr and the compiler will assume that this is a member variable of Base<T> or a method of Base<T> (this is what it will do because Base<T>::TPtr is a 'dependant name' and unfortunately in this case the compiler will assume variable or function instead of type) thus making the declaration invalid.

The keyword typename allow the compiler to know explicitly that TPtr names a type.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜