我实现了一个非常简单的图形模型,其中我有一个包含前向列表的结构,其中包含指向它的邻居。这些邻居又是相同类型的结构。
#include <iostream>
#include <vector>
#include <set>
#include <forward_list>
#include <fstream>
using namespace std;
typedef struct Vertex Vertex;
struct Vertex {
unsigned id;
forward_list<Vertex*> _next;
};
typedef set<Vertex> Graph;
typedef vector<Vertex*> Index;
typedef pair<unsigned, unsigned> Edge;
typedef forward_list<Vertex*> Neighbors;
// Function: process_line()
// Purpose: process a specific line from the file.
// Params: line to process
Edge process_line(string line){
unsigned vertex_from;
unsigned vertex_to;
int idx = line.find(" ");
vertex_from = (unsigned)stoul(line.substr(0, idx));
vertex_to = (unsigned)stoul(line.substr(idx+1, line.length()));
return make_pair(vertex_from, vertex_to);
}
// Function: load_graph()
// Purpose: load graph from file in relation
// Params: path, and reference to graph and index
bool load_graph(string file_path, Graph &graph, Index &index){
string line;
ifstream file(file_path);
bool foundEmptyLine = false;
if(file.is_open()){
while(getline(file, line)){
if(line.empty()){
foundEmptyLine = true;
}
if(!foundEmptyLine){
// processing vertexes
Vertex *vertex = new Vertex;
vertex->id = stoul(line);
graph.emplace(*vertex);
index.emplace_back(vertex);
}else{
// Processing relations
Edge edge = process_line(line);
Vertex* neighbor = index.at(edge.second);
// Lookup edge in index
index.at(edge.first)->_next.push_front(neighbor);
}
}
file.close();
}else{
cout << "Unable to open " << file_path;
return false;
}
return true;
}
void print_graph(Graph &graph){
for(Graph::iterator it = graph.begin(); it != graph.end(); ++it){
// Print item.
cout << "Node: " << it->id << endl << "Neighbors:";
for(Neighbors::iterator neigh = it->_next.begin(); neigh != it->_next.end(); ++neigh){
// Print item.
cout << (*neigh)->id;
}
}
}
// Entry point.
int main() {
Graph graph;
Index index;
load_graph("graph_1.txt", graph, index);
print_graph(graph);
}
一直在努力,直到我尝试循环图中的顶点,然后循环顶点的所有邻居。 (print_graph函数)我收到此错误:
错误:来自&#39; const_iterator&#39; (又名 &#39; __ forward_list_const_iterator *&gt;&#39;)到&#39;邻居:: iterator&#39; (又名 &#39; __ forward_list_iterator *&gt;&#39;)
提前致谢。
答案 0 :(得分:2)
问题在于
Graph::iterator it = graph.begin()
将返回类型为Graph::iterator
的迭代器,该迭代器等于Graph::const_iterator
。请参阅http://en.cppreference.com/w/cpp/container/set(请注意,这已在C ++ 11中更改)。
所以当你打电话时
Neighbors::iterator neigh = it->_next.begin()
这将返回std::forward_list::const_iterator
(因为*it
为const
),当然您无法分配给std::forward_list::iterator
。
无论如何,我建议在这里使用auto
作为类型,并且,因为您无论如何都不需要写访问权限,所以您应该使用cbegin()
,它会在任何地方返回const_iterator
情况下。
答案 1 :(得分:2)
此错误的原因非常微妙。 std::set
的{{1}}类型实际上与iterator
类型相同。这是有道理的;集合需要始终保证每个元素都是唯一的。如果您可以自由修改元素,它将无法提供保证。
考虑以下一行:
const_iterator
for(Graph::iterator it = graph.begin(); it != graph.end(); ++it){
是it
,其行为类似于iterator
。您无法修改迭代器指向的内容。
您可以按如下方式验证:
const_iterator
然后是这一行:
由于上述原因,it->id = 1; // will result in a compilation error
for(Neighbors::iterator neigh = it->_next.begin(); neigh != it->_next.end(); ++neigh){
为it->_next
,因此在其上调用forward_list<Vertex*> const
会返回begin()
。
这是最终导致错误的原因:您无法将const_iterator
转换为const_iterator
。
治愈很简单:只需使用iterator
:
const_iterator
甚至更好,使用for(Neighbors::const_iterator neigh = it->_next.begin(); neigh != it->_next.end(); ++neigh){
:
auto
甚至更简单,基于范围的for(auto neigh = it->_next.begin(); neigh != it->_next.end(); ++neigh){
循环:
for
请注意,修复此特定错误后,您会找到其他错误。您还缺少必要的for (auto const& neigh : it->_next) {
// Print item.
cout << neigh->id;
}
,这会使您的代码与平台相关(即它适用于GCC,但不适用于Visual C ++)。