Accessing Inherited Variable from Templated Parent Class

Can't access variable in template base class

Hehe, my favourite C++ oddity!

This will work:

void foo()
{
b = this->a;
// ^^^^^^
}

Unqualified lookup doesn't work here because the base is a template. That's just the way it is, and comes down to highly technical details about how C++ programs are translated.

Accessing variables from base template class in derived class constructor in C++

arr is a dependent name now. It depends on T. What if there is some T for which Base<T> is specialized to not have an arr? Specifically, from [temp.dep]:

In the definition of a class or class template, the scope of a dependent base class (14.6.2.1) is not examined
during unqualified name lookup
either at the point of definition of the class template or member or during
an instantiation of the class template or member.

Base<T> is a dependent base class - it depends on the template parameter T, so its scope is not examined during unqualified name lookup. The way around this is to use qualified name lookup. That is, either the class name:

parr = &Base<T>::arr[0];

or just with this:

parr = &this->arr[0];

templates: parent class member variables not visible in inherited class

This is because the template parent of a template class is not instantiated during the compilation pass that first examines the template. These names appear to be non-dependent on the particular template instantiation, and therefore the definitions need to be available. (If you never look at the definition of arrayListType, then reading the code of unorderedArrayListType it would appear the list and length need to be some sort of globals.)

You'll need to tell the compiler explicitly that the names are in fact dependent on the instantiation of the parent.

One way, using this-> before all the inherited names: this->list, this->length.

Another way, using declarations: using arrayListType<elemType>::length; etc (for example in the private section of the derived class).


A FAQ entry on this: https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members

Derived template-class access to base-class member-data

You can use this-> to make clear that you are referring to a member of the class:

void Bar<T>::BarFunc () {
std::cout << this->_foo_arg << std::endl;
}

Alternatively you can also use "using" in the method:

void Bar<T>::BarFunc () {
using Bar<T>::_foo_arg; // Might not work in g++, IIRC
std::cout << _foo_arg << std::endl;
}

This makes it clear to the compiler that the member name depends on the template parameters so that it searches for the definition of that name in the right places. For more information also see this entry in the C++ Faq Lite.

Access to protected member variable from derived inner class in a templated parent class

You can use a using declaration.

template <typename T>
struct Temp
{
struct BaseIterator
{
protected:
int pos;
BaseIterator() : pos(0) {}
};

struct LeafIterator : public BaseIterator
{
using BaseIterator::pos;
int * operator * () { return &pos; }

LeafIterator() : BaseIterator() {}
};
};

int main()
{
Temp<int>::LeafIterator leaf_iterator;
}

This compiles fine in GCC 8.2.0.

access static member of template parent class

The compiler does not resolve the inherited members for template base classes, due to the fact that you may have specializations that do not define the member, and in that case the whole parsing/name resolving business will become quite difficult.

If your member is non-static, then using this->n_parent "assures" the compiler that n_parent is indeed a member of the base class. If the member is static, there is no this pointer (as you mention), so the only choice is to qualify the base class as you do.

Related: Derived template-class access to base-class member-data

Visibility of members of base template class not directly inherited

You are using A<X> where a base class is expected.

[namespace.udecl]

3 In a using-declaration used as a member-declaration, each
using-declarator's nested-name-specifier shall name a base class of
the class being defined.

Since this appears where a class type is expected, it is known and assumed to be a type. And it is a type that is dependent on the template arguments, so it's not looked up immediately.

[temp.res]

9 When looking for the declaration of a name used in a template
definition, the usual lookup rules ([basic.lookup.unqual],
[basic.lookup.argdep]) are used for non-dependent names. The lookup of
names dependent on the template parameters is postponed until the
actual template argument is known ([temp.dep]).

So it's allowed on account of the compiler not being able to know any better. It will check the using declaration when the class is instantiated. Indeed, one can put any dependent type there:

template<bool> struct D{};

template <bool X>
struct C : public B<X> {
using D<X>::x;
C() { x = 1; }
};

This will not be checked until the value of X is known. Because B<X> can bring with it all sorts of surprises if it's specialized. One could for instance do this:

template<>
struct D<true> { char x; };

template<>
struct B<true> : D<true> {};

Making the above declaration be correct.



Related Topics



Leave a reply



Submit