我写了这些代表图表的类:
class Node{
public:
typedef std::vector<Node>::iterator iterator;
iterator begin() {return neigh.begin();}
iterator end() {return neigh.end();}
public:
Node(std::string n) : name(n) {}
std::string getName() {return name; }
void addNeigh(Node n){
neigh.push_back(n);
}
private:
std::string name;
std::vector<Node> neigh;
};
class Map{
public:
typedef std::vector<Node>::iterator iterator;
iterator begin() {return nodes.begin();}
iterator end() {return nodes.end();}
public:
Map(std::string n) : map_name(n) {}
void addNode(Node n){
nodes.push_back(n);
}
std::string getName() { return map_name; }
int getNumNodes() {return nodes.size();}
private:
std::string map_name;
std::vector<Node> nodes;
};
然后我想编写一个函数printGraph
,使用特征打印一些图形信息:
template<typename T>
struct GraphTraits{
};
template<>
struct GraphTraits<Map>{
typedef Map::iterator node_iterator;
static node_iterator node_begin(Map map){ return map.begin();}
static node_iterator node_end(Map map) { return map.end();}
static std::string getName(Map m) {return m.getName();}
};
template<typename T>
void printGraph(T t){
std::cout << std::endl
<< "--------------------------------------" << std::endl
<< "| printGraph |" << std::endl
<< "--------------------------------------" << std::endl;
std::cout << "Graph name: " << GraphTraits<T>::getName(t) << std::endl;
for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
it != e; ++it) {
std::cout<< (*it).getName() << std::endl; }
}
如果我尝试编译此代码,我会收到以下错误:
grafo.cpp:75:37: error: expected ';' in 'for' statement specifier
for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
^
grafo.cpp:75:37: error: use of undeclared identifier 'it'
grafo.cpp:75:73: error: use of undeclared identifier 'e'
for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
^
grafo.cpp:76:9: error: use of undeclared identifier 'it'
it != e; ++it) {
^
grafo.cpp:76:15: error: use of undeclared identifier 'e'
it != e; ++it) {
^
grafo.cpp:76:16: error: expected ')'
it != e; ++it) {
^
grafo.cpp:75:6: note: to match this '('
for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
^
grafo.cpp:76:20: error: use of undeclared identifier 'it'
it != e; ++it) {
^
grafo.cpp:75:23: error: unexpected type name 'node_iterator': expected expression
for(GraphTraits<T>::node_iterator it = GraphTraits<T>::node_begin(t), e = GraphTraits<T>::node_end(t);
^
grafo.cpp:104:3: note: in instantiation of function template specialization 'printGraph<Map>' requested here
printGraph(mappa);
^
我可以成功地解决和编译:
for(GraphTraits<T>::node_iterator....
使用:
for(GraphTraits<Map>::node_iterator....
但这会使printGraph
失去它的普遍性。
有人可以给我一些提示来解决问题吗?
在Generale中说,是否可以使用Traits强制数据类型定义?我的意思是:
template<typename T>
struct ATraits{
-> type "iterator" must be defined
};
这样每个专业都必须定义:
typedef ..something.. iterator;
答案 0 :(得分:4)
您忘记使用typename
关键字。
在GraphTraits<Map>::node_iterator
中,编译器知道使用了GraphTraits
的特殊化,并且可以发现node_iterator
是一个typedef。
在GraphTraits<T>::node_iterator
中,它不知道将使用什么专业化,因为T
尚未知晓。因此它假设node_iterator
是成员变量,而不是类型。你必须纠正这个假设。说typename GraphTraits<T>::node_iterator
要求GraphTraits
的每个特化都提供一个typedef,你需要“概念”,这些概念是为C ++ 11提出的,但是必须延迟到将来的版本。所以今天在C ++中是不可能的。无论何时实际使用printGraph
(正式地,在实例化printGraph<T>
函数模板的每个模板函数实例期间),编译器都会仔细检查GraphTraits<T>::node_iterator
是否真的是一种类型(因为现在它知道T
并且可以执行重载解析。)