Possible Duplicate:
Accessing inherited variable from templated parent class
I have been implementing a binary heap as a subclass of priority_queue, and run into a situation I cannot understand, despite considerable effort. Here is the working version of the code. (Background: c is priority_queue’s backing vector.)
#include <queue>
using namespace std;
template <class nodetype>
class BinaryHeap : public priority_queue<int> {
public:
BinaryHeap() { vec = &c; }
vector<nodetype> *vec;
};
int main() {
BinaryHeap<int> b;
}
However, when you change the superclass to:
class BinaryHeap : public priority_queue<nodetype>
…the compiler complains about the usage of c:
h.cpp: In constructor ‘BinaryHeap<nodetype>::BinaryHeap()’:
h.cpp:10: error: ‘c’ was not declared in this scope
This seems all the more strange because:
-
“[c] is equivalent to this->c” (ref) – and if you use
vec = &this->c, it does indeed compile. -
If you add a using-declaration,
using priority_queue<nodetype>::cto BinaryHeap, again, it compiles. But this using-declaration ought to be unnecessary.
Edit:
So, apparently this happens because “the compiler does not look in dependent base classes when looking up nondependent names” (ref) – “c” does not depend on a template parameter, and so is nondependent, and priority_queue<nodetype> does depend on a template parameter – nodetype – so is dependent.
priority_queue<int>, on the other hand, doesn’t depend on nodetype, and so is nondependent, and so the compiler does look in it for names when resolving other nondependent names.
Is this correct? And if so:
Why does the standard mandate this behaviour, when “[looking] in dependent base classes when looking up nondependent names” is clearly possible. What is the benefit? A compile-time performance optimisation?
In the end its simply a matter of the standard defining such a behaviour for templates. The (C++11) standard says the following about non dependent name resolution in [temp.nondep] (14.6.3) :
Since
cdoesn’t obviously depend on a template parameter the compiler treats it as a non-dependent name. So what happens is basically the following: When the compiler looks atBinaryHeapthe actual type ofnotetypeis unknown and thereforepriority_queue<nodetype>is too, since it depends onnodetype(it could be a partial specialization). Therefore the compiler can’t look into that type for the resolution (since we are talking about the point where the template is defined, not where it is instantiated). So it looks in the containing scopes for something calledc, finding none and therefore rejecting the code. Usingthis->c(orusing priority_queue<nodetype>::c) makesca dependent name (since its not a member ofBinaryHeapit must be a member ofpriority_queue<nodetype>), so the name lookup is delayed until the point of instantiation of the template, wherenotetypeis known and the compiler can therefore search inpriority_queue<nodetype>.For your edit: yes, that is correct