我有下面的代码,编译错误是: 为什么graph_algorithm不能在图类中找到顶点类?
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 :(得分:2)
作为一项规则,如果您在使用模板时看到编译错误,那么第一个的一个疑问应该是您忘记为依赖类型编写typename
,例如这样:
bool operator()(graph<T>::vertex &v1, graph<T>::vertex &v2)
应该是这样的:
bool operator()(typename graph<T>::vertex &v1, typename graph<T>::vertex &v2)
你看到typename
了吗?同样,您还需要在代码中的任何位置编写typename
- 无论您在何处使用依赖类型。
如果你想知道什么是依赖类型,放在哪里以及放置typename
依赖类型的原因,请阅读:
除此之外,您还需要了解private
成员和public
成员之间的区别 - 无论是类型还是变量。在您的情况下,嵌套类型为private
,我认为应该是public
。