我找到了Graphs的开源类库。当我将它包含在我的项目中时,它有很多错误,我试图修复它们。但是有一个编译错误,我无法解决它。
基类:
template <typename K, typename W, typename T>
class _base_graph
{
//...
protected:
std::map<K, T> nod;
std::list<edge> edg;
};
派生类:
template <typename K, typename T = void*>
class graph : public _base_graph<K, void*, T>
{
//...
public:
void add_edge(const K& k1, const K& k2);
};
方法体:
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");
// ...
}
但我的gcc编译器显示错误:
错误:未在此范围内声明'nod'
您可以在this在线编译器中找到并测试我的代码。
答案 0 :(得分:8)
你需要
this->nod.find(k2);
或
_base_graph<K, void*, T>::nod.find ....;
基类和派生类是模板,在代码nod
中是一个非依赖名称,因此在graph
的声明中查找。这是两阶段查找的第一阶段。在这个阶段,编译器(如果遵循标准的名称查找规则)不可能知道nod
的意思,因为它在第二阶段之前不考虑基类。因此有必要告诉编译器在第二阶段应该查找nod
。为此,我们通过使用上述表单之一明确告诉它nod
在基类中。
这种行为的原因是,在派生类'定义时,不应该知道_base_graph<K, void*, T>::
包含什么,以允许添加的模板的特化甚至隐藏名字。因此,上面的技巧确保在所有信息都可用时,在派生类的实例化时查找名称。
总之,这里有两个问题:
nod
不是依赖名称,因此会在第一阶段进行查找。nod
的基类模板在第二阶段之前不可用,因此无法解析名称。通过使用this->nod
或_base_graph<K, void*, T>::nod
,我们明确地处理了一个从属名称,迫使查找在第二阶段进行。
见第7至10点here。
感谢@ DavidRodriguez-dribeas澄清了两阶段查找的一些细节。
答案 1 :(得分:3)
nod
是依赖库的成员(依赖于模板参数的成员)。您需要使用基础名称来限定呼叫,例如_base_graph<K, void*, T>::nod
或this->nod
。
或者,您也可以在函数或类范围内引入using _base_graph<K, void*, T>::nod
的名称。