我写了这些表示图形的类:
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
失去了普遍性。有人可以给我一些解决问题的提示吗?
概括地说,是否可以使用“特质”来强制定义数据类型?我的意思是:
template<typename T>
struct ATraits{
-> type "iterator" must be defined
};
这样每个专业都必须定义:
typedef ..something.. iterator;
最佳答案
您忘记使用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
并可以执行重载解析)。