"Not Declared in This Scope" Error with Templates and Inheritance

not declared in this scope error with templates and inheritance

myOption is not a dependent name, i.e. it doesn't depend on the template arguments explicitly so the compiler tries to look it up early. You must make it a dependent name:

template <typename InterfaceType>
void ChildClass<InterfaceType>::set()
{
this->myOption = 10;
}

Now it depends on the type of this and thus on the template arguments. Therefore the compiler will bind it at the time of instantiation.

This is called Two-phase name lookup.

inheriting from a template class: member was not declared at this scope

If you use a name in a way that doesn't reference the template parameter visually, it should absolutely not depend on the template parameter!

void foo();

template <typename T>
struct A : T {
void bar() {
foo();
}
};

It could be very bad that if T has a foo member function then the call resolves to the member and not to the global function.

If there is no global foo you could argue that it could resolve to a member function/data member as fallback, but that would complicate the language and could be confusing to get right ("I want to call member foobar but I didn't realize that there was a global function that happens to have the right signature").

In your example someone could specialize A with no member data member. Would a hypothetical global member variable be used instead? With this-> it's unambiguous.

varName was not declared in this scope using templates and inheritance in C++

If you are using an older compiler, you need a space between the two >> after 153.

See Template within template: why "`>>' should be `> >' within a nested template argument list"

Protected member is not declared in this scope in derived class

To fix this, you need to specify Base<T>::data_.clear() or this->data_.clear(). As for why this happens, see here.

variable not declared in scope using template inheritance

This is best explained in the C++ FAQ: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19.

To paraphrase:

Within OMCollection<Concept>::add(), the name count does not
depend on template parameter Concept, so count is known as a
nondependent name. On the other hand, OMStaticArray<Concept> is
dependent on template parameter Concept so OMStaticArray<Concept>
is called a dependent name.

Here's the rule: the compiler does not look in dependent base classes
(like OMStaticArray<Concept>) when looking up nondependent names
(like count).

As to why this compiled in an older compiler, the reason is probably that the older compiler wasn't fully compliant with the C++ standard.

inheritance doesn't work as it should when using templates

A quick fix is to apply this before the variable:

 this->n = this->n + 1;
return this->n;

The reason is that the compiler makes no assumptions about template base class members (n in this case, which is dependent on the type T) in case there is a partial specialization of the base class that does not include some of these members.

Inheritance of class members, mixed with templates

You need to use this->m_t to make it a dependent name. When templates are compiled, names are looked up in two stages. Non-dependent names are looked up when the compiler first parses the template. Dependent names are looked up when the template is instantiated. Changing it to this->m_t delays look-up until after the get function is actually instantiated, in which case the base class type is known and the compiler can verify the member's existence.

C++ was not declared in this scope when overriding a pure virtual method in a derived class

In the expression:

    cout << "v_b = " << v_b << endl;

v_b is a non-dependent expression (i.e. it does not look like it depends on the template arguments. For a non-dependent expression the first phase lookup must resolve the symbol, and it will do so by looking only in non-dependent contexts. This does not include a templated base (as it does depend on the type argument). The simple fix is to qualify the call with this:

    cout << "v_b = " << this->v_b << endl;

Now it is a dependent expression (this which clearly depends on the instantiating type), and lookup is delayed to the second phase where the type is substituted and the bases can be checked.



Related Topics



Leave a reply



Submit