Reputation: 56549
I found an open source class library for Graphs. When I included it in my project it has many errors and I tried to fix them. But there is a compile error that I can not solve it.
Base class:
template <typename K, typename W, typename T>
class _base_graph
{
//...
protected:
std::map<K, T> nod;
std::list<edge> edg;
};
Derived class:
template <typename K, typename T = void*>
class graph : public _base_graph<K, void*, T>
{
//...
public:
void add_edge(const K& k1, const K& k2);
};
Method body:
template <typename K, typename T>
void graph<K, T>::add_edge(const K& k1, const K& k2)
{
if (nod.find(k1) == nod.end() || nod.find(k2) == nod.end()) // <-- error!!
throw std::string("add_edge: Node does not exist");
// ...
}
But my gcc compiler show me an error:
error: ‘nod’ was not declared in this scope
You can find and test mycode in this online compiler.
Upvotes: 3
Views: 208
Reputation: 227608
You need
this->nod.find(k2);
or
_base_graph<K, void*, T>::nod.find ....;
The base and the derived classes are templates, and in your code nod
is a non-dependent name, and so is looked up at the point of graph
's declaration. This is the first phase of the two-phase lookup. At this stage, it is impossible for the compiler (provided it follows the name lookup rules of the standard) to know what nod
means, because it does not consider the base class until the second phase. So it is necessary to tell the compiler that nod
should be looked up in the second phase. To do this, we explicitly tell it that nod
is in a base class by using one of the forms above.
The reason for this behaviour is that at the point of the derived class' definition, it should not possible to know what _base_graph<K, void*, T>::
contains, to allow for specializations of the template that add and even hide names. So the trick above makes sure that the names are looked up at the point of the derived class' instantiation, when all the information is available.
In summary, there are two issues in play here:
nod
is not a dependent name, so it would be looked up in the first phase.nod
, is not available until the second phase, so the name cannot be resolved.By using this->nod
or _base_graph<K, void*, T>::nod
, we are explicitly dealing with a dependent name, forcing the lookup to take place in the second phase.
See points 7 to 10 here.
Thanks to @DavidRodriguez-dribeas for clarifying some of the finer points of the two phase look-up.
Upvotes: 8
Reputation: 59841
nod
is a member of a dependent base (one that depends on template parameters). You either need to qualify the call with the name of the base, e.g. _base_graph<K, void*, T>::nod
or with this->nod
.
Alternatively you can also bring in names with using _base_graph<K, void*, T>::nod
in either function or class scope.
Upvotes: 3