2012-09-17 11 views
1

强制类型定义我写这些类代表一个图:与性状

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); 
^

我可以解决和编译s uccessfully代:

for(GraphTraits<T>::node_iterator.... 

有:

for(GraphTraits<Map>::node_iterator.... 

但这使得printGraph失去它的普遍性。

有人可以给我一些提示来解决问题吗?

在兴业谈话时,是有可能使用一个性状来强制一个数据类型定义?我的意思是:

template<typename T> 
struct ATraits{ 
-> type "iterator" must be defined 
}; 

使得每个专业化有定义:

typedef ..something.. iterator; 

回答

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,并可以执行重载决议)。

+0

好吧,可圈可点。非常感谢你。 – Aslan986