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 namecount
does not
depend on template parameterConcept
, socount
is known as a
nondependent name. On the other hand,OMStaticArray<Concept>
is
dependent on template parameterConcept
soOMStaticArray<Concept>
is called a dependent name.Here's the rule: the compiler does not look in dependent base classes
(likeOMStaticArray<Concept>
) when looking up nondependent names
(likecount
).
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
Are Parentheses Around the Result Significant in a Return Statement
Does the C++ Volatile Keyword Introduce a Memory Fence
Why Can't I Capture This By-Reference ('&This') in Lambda
Compile the Python Interpreter Statically
Nested Templates with Dependent Scope
Why Not Use Pointers for Everything in C++
List of Standard Header Files in C and C++
C++ Uninitialized Local Variable
Which Boost Features Overlap with C++11
Difference Between a Virtual Function and a Pure Virtual Function
Which Is Better Option to Use for Dividing an Integer Number by 2
Write Applications in C or C++ for Android
Class Variables: Public Access Read-Only, But Private Access Read/Write
How to Generate a Random Double Uniformly Distributed Between 0 and 1 from C++
Unordered_Map Hash Function C++
Portability of Binary Serialization of Double/Float Type in C++
May Std::Vector Make Use of Small Buffer Optimization
Is It Reasonable to Use Std::Basic_String<T> as a Contiguous Buffer When Targeting C++03