2012-04-08 21 views
0

以下のコードがあります。コンパイラエラーは グラフクラス内で頂点クラスを見つけることができないのはなぜですか?原則としてクラス内部で定義されたC++クラスをテンプレート内に見つけることができません

graph_algorithms.h:26:33: error: ‘Graph::graph<T>::vertex’ is not a type 
graph_algorithms.h:26:55: error: ‘Graph::graph<T>::vertex’ is not a type 
graph_algorithms.h: In member function ‘bool Graph::graph_algorithm<T>::vertex_comparer::operator()(int&, int&)’: 
graph_algorithms.h:28:10: error: ‘t1’ was not declared in this scope 
graph_algorithms.h:28:21: error: ‘t2’ was not declared in this scope 
graph_algorithms.h:28:33: error: expected primary-expression before ‘return’ 
graph_algorithms.h:28:33: error: expected ‘:’ before ‘return’ 
graph_algorithms.h:28:33: error: expected primary-expression before ‘return’ 
graph_algorithms.h:28:33: error: expected ‘;’ before ‘return’ 
graph_algorithms.h:29:7: warning: no return statement in function returning non-void [-Wreturn-type] 

#ifndef GRAPH_H_ 
#define GRAPH_H_ 

#include <list> 
#include <algorithm> 
#include <vector> 
#include <utility> 
#include <iostream> 
#include <stdexcept> 
#include <assert.h> 

namespace Graph 
{ 
    template <class T> 
    class graph 
    { 
    // Forward Declarations 
    private: 
    class vertex; 
    class edge; 
    template <class U> 
    friend class graph_algorithm; 

    public : 
    explicit graph(const std::vector<std::pair<T, T> > &vertices); 
    ~graph() 
    {} 
    void insert_vertex_pair_by_keys(T key1, T key2); 
    const std::list<vertex> &vertices() const {return m_Vertices;} 

    // Private contained classes 
    private: 
    struct edge 
    { 
     edge(vertex *edge, T weight) : 
     m_Edge(edge), 
     m_Weight(weight) 
     {} 
     vertex *m_Edge; 
     T m_Weight; 
    }; // END EDGE 

    class vertex 
    { 
    public: 
     vertex(T key) : 
     m_Key(key) 
     {} 
     void connect_edge(vertex *adjacent); 
     const T key() const {return m_Key;} 
     const std::list<edge> &edges() const {return m_Edges;} 
    private: 
     std::list<edge> m_Edges; 
     T m_Key; 
     bool contains_edge_to_vertex_with_key(const T key); 
    }; // END VERTEX 

    // Private methods and member variables 
    private: 
    std::list<vertex> m_Vertices; 
    vertex *contains_vertex(const T key); 
    }; 
} 

/*! 
* Constructor of graph: Take a pair of vertices as connection, attempt 
* to insert if not already in graph. Then connect them in edge list 
*/ 
template <class T> 
Graph::graph<T>::graph(const std::vector<std::pair<T, T> > &vertices_relation) 
{ 

#ifndef NDEBUG 
    std::cout << "Inserting pairs: " << std::endl; 
#endif 

    typename std::vector<std::pair<T, T> >::const_iterator insert_it = vertices_relation.begin(); 
    for(; insert_it != vertices_relation.end(); ++insert_it) { 

#ifndef NDEBUG 
    std::cout << insert_it->first << " -- > " << insert_it->second << std::endl; 
#endif 

    /* 
    * Insert vertex by key pairs into the graph 
    */ 
    insert_vertex_pair_by_keys(insert_it->first, insert_it->second); 
    } 

#ifndef NDEBUG 
    std::cout << "Printing results: " << std::endl; 
    typename std::list<vertex>::iterator print_it = m_Vertices.begin(); 
    for(; print_it != m_Vertices.end(); ++print_it) { 
    std::cout << print_it->key() << " --| "; 
    typename std::list<edge>::const_iterator edge_it = print_it->edges().begin(); 
    for(; edge_it != print_it->edges().end(); ++edge_it) { 
     std::cout << edge_it->m_Edge->key() << " --> "; 
    } 
    std::cout << std::endl; 
    std::cout << "|" << std::endl; 
    std::cout << "V" << std::endl; 
    } 
#endif 
} 

/*! 
* Takes in a value of type T as a key and 
* inserts it into graph data structure if 
* key not already present 
*/ 
template <typename T> 
void Graph::graph<T>::insert_vertex_pair_by_keys(T key1, T key2) 
{ 
    /* 
    * Check if vertices already in graph 
    */ 
    Graph::graph<T>::vertex *insert1 = contains_vertex(key1); 
    Graph::graph<T>::vertex *insert2 = contains_vertex(key2); 

    /* 
    * If not in graph then insert it and get a pointer to it 
    * to pass into edge. See() for information on how 
    * to build graph 
    */ 
    if (insert1 == NULL) { 
    m_Vertices.push_back(vertex(key1)); 
    insert1 = contains_vertex(key1); 
    } 
    if (insert2 == NULL) { 
    if (key1 != key2) { 
     m_Vertices.push_back(vertex(key2)); 
    } 
    insert2 = contains_vertex(key2); 
    } 

#ifndef NDEBUG 
    assert(insert1 != NULL && "Failed to insert first vertex"); 
    assert(insert2 != NULL && "Failed to insert second vertex"); 
#endif 

    /*! 
    * At this point we should have a vertex to insert an edge on 
    * if not throw an error. 
    */ 
    if (insert1 != NULL && insert2 != NULL) { 
    insert1->connect_edge(insert2); 
    insert2->connect_edge(insert1); 
    } else { 
    throw std::runtime_error("Unknown"); 
    } 
} 

/*! 
* Search the std::list of vertices for key 
* if present return the vertex to indicate 
* already in graph else return NULL to indicate 
* new node 
*/ 
template <typename T> 
typename Graph::graph<T>::vertex *Graph::graph<T>::contains_vertex(T key) 
{ 
    typename std::list<vertex >::iterator find_it = m_Vertices.begin(); 
    for(; find_it != m_Vertices.end(); ++find_it) { 
    if (find_it->key() == key) { 
     return &(*find_it); 
    } 
    } 
    return NULL; 
} 

/*! 
* Take the oposing vertex from input and insert it 
* into adjacent list, you can have multiple edges 
* between vertices 
*/ 
template <class T> 
void Graph::graph<T>::vertex::connect_edge(Graph::graph<T>::vertex *adjacent) 
{ 
    if (adjacent == NULL) 
    return; 

    if (!contains_edge_to_vertex_with_key(adjacent->key())) { 
    Graph::graph<T>::edge e(adjacent, 1); 
    m_Edges.push_back(e); 
    } 
} 

/*! 
* Private member function that check if there is already 
* an edge between the two vertices 
*/ 
template <class T> 
bool Graph::graph<T>::vertex::contains_edge_to_vertex_with_key(const T key) 
{ 
    typename std::list<edge>::iterator find_it = m_Edges.begin(); 
    for(; find_it != m_Edges.end(); ++find_it) { 
    if (find_it->m_Edge->key() == key) { 
     return true; 
    } 
    } 
    return false; 
} 
#endif 

#ifndef GRAPH_ALGORITHMS_H_ 
#define GRAPH_ALGORITHMS_H_ 

#include "graph.h" 

namespace Graph 
{ 
    template <class T> 
    class graph_algorithm 
    { 
    // Forward declarations of 
    // internal classes 
    private : 
    class vertex_comparer; 

    public : 
    graph_algorithm(graph<T> *&graph) : 
     m_Graph(graph) 
    {} 

    // Definition of internal classes 
    private : 
    class vertex_comparer 
    { 
    public: 
     bool operator()(graph<T>::vertex &v1, graph<T>::vertex &v2) 
     { 
     (t1.key() < t2.key()) ? return true : return false; 
     } 
    }; 
    private : 
    graph<T> *m_Graph; 
    }; 
} 

#endif 

#include "graph_algorithms.h" 
#include "graph.h" 
#include <cstdlib> 

int main(int argc, char *argv[]) 
{ 
    std::vector<std::pair<int, int> > graph_vect; 
    for (int i = 0; i < 100; i++) { 
    graph_vect.push_back(std::pair<int, int>(rand()%20, rand()%20)); 
    } 
    Graph::graph<int> my_graph(graph_vect); 
    return 0; 
} 
+0

あなたの頂点クラスはプライベートクラスです。 –

+0

クラスエッジの前方宣言が間違っていると思います。 – CapelliC

+0

@chacその訂正のおかげで。それは使用されていないので、コンパイラは一度も不平を言うことはありません –

答えて

2

テンプレートで作業するときに、コンパイルエラーが表示された場合、その後、最初少数の疑問の一つはする必要がありますあなたはdependeのためにtypenameと書くのを忘れてしまったこのようなNTの種類、:

bool operator()(typename graph<T>::vertex &v1, typename graph<T>::vertex &v2) 

あなたがtypenameを参照してください。むしろ、このする必要があります

bool operator()(graph<T>::vertex &v1, graph<T>::vertex &v2) 

?同様に、従属型を使用している場合でも、どこにでもtypenameをコード内に記述する必要があります。

あなたが依存型であるかを知りたい場合は、どこで置くか、なぜ依存型でtypenameを置くために、この読み:それは別に

、またあなたをprivateメンバーとpublicメンバーの違いを理解する必要があります - それらはタイプまたはの変数となります。あなたのケースでは、ネストされたタイプはprivateです。これはpublicです。

+0

しかし、参照するクラスはfriendと宣言されています。十分ではありませんか? – CapelliC

+0

@chac:私はそれに気付かなかった。また、私は構文についてよく分かりません。 – Nawaz

+1

@Nawazは助けてくれてありがとう、あなたはtypenameについて見落としている。そして、私は頂点とエッジをプライベートにしました。ユーザーがコンセプトについて心配する必要はないからです。彼らが頂点や端からのデータを必要とするならば、T&get_data()メソッドを提供します。しかし、私はまだそれが必要なので、グラフアルゴリズムがこれらのものにアクセスできるようにしたい。だから私はそれを友人にしました。 –

関連する問題