Wednesday, October 8, 2008

c++: inheritance from "template" class and dependance on template parameter

You may say it's quite weird that you are unable to access members of base class which depends on template parameter.

template<typename T>
class A
{
    public:
        T member;
};

template<typename T>
class B: public A<T>
{
    public:
        B();
};

template<typename T>
<T>::B()
{
    T t;
    member = t;
}
This code will raise an error that 'member' has not been found. An error occurs because of the interactions taking place in the c++ lookup rules. It comes down to that something is dependent upon some "<T>". Not that T depends upon say a typedef, but it depends upon a template parameter. In particular the use of A<T> depends upon the template parameter T, therefore the use of this base's members need to follow the rules of dependent name lookup, and hence are not directly allowed in the code above as written. To make this code work you may
  • Qualify the name with this->
    this->member = t;
  • Qualify the name with A<T>::
    A<T>::member = t;
  • Use a 'using' directive in the class template
    template<typename T>
    class A
    {
        public:
            T member;
    };
    
    template<typename T>
    class B: public A<T>
    {
        using A<T>::member;
        public:
            B();
    };
    
    template<typename T>
    B<T>::B()
    {
        T t;
        member = t;
    }
There is not everything clear with methods that depend on own template parameter.
template<typename T>
class A
{
    public:
        template<typename U>
        void func();
};

template<typename T>
template<typename U>
void
A<T>::func()
{
}

template<typename T>
class B: public A<T>
{
    public:
        B();
};

template<typename T>
B<T>::B()
{
    A<T>::func<int>();
    this->func<int>();
}
You can't write
this->member = t;
nor
A<T>::member = t;
The compiler assumes that the < is a less-than operator. In order for the compiler to recognize the function template call, you must add the template quantifier.
template<typename T>
B<T>::B()
{
    A<T>::template func<int>();
    this->template func<int>();
}
Some compilers(or their versions) don't actually parse the template until the instantiation. Those may successfully compile the code w/o specifying 'template' keyword. Without knowing the instantiation type, it can't know what 'func' refers to. In order to parse correctly, however, the compiler must know which symbols name types, and which name templates. 'template' keyword helps compiler to get that A<T>::func<int> is a template.

No comments: