[英]Struct with forward_list with pointers to itself
我正在實現一個非常簡單的圖形模型,其中有一個結構,該結構包含帶有指向其鄰居的指針的轉發列表。 這些鄰居又是相同類型的結構。
#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函數)出現此錯誤:
錯誤:沒有從'const_iterator'(aka'__forward_list_const_iterator *>')到'Neighbors :: iterator'(aka'__forward_list_iterator *>')的可行轉換
提前致謝。
問題是
Graph::iterator it = graph.begin()
將返回Graph::iterator
類型的迭代器,該迭代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
。
此錯誤的原因非常微妙。 std::set
的iterator
類型實際上與const_iterator
類型相同。 這很有道理; 一個集合需要始終保證每個元素都是唯一的。 如果您可以自由修改元素,則將無法提供保證。
考慮以下行:
for(Graph::iterator it = graph.begin(); it != graph.end(); ++it){
it
是一個類似於const_iterator
的iterator
。 您無法修改迭代器指向的對象。
您可以如下驗證:
it->id = 1; // will result in a compilation error
然后是這一行:
for(Neighbors::iterator neigh = it->_next.begin(); neigh != it->_next.end(); ++neigh){
由於上述原因, forward_list<Vertex*> const
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;
}
請注意,解決此特定錯誤后,您將找到其他錯誤。 您還缺少必要的#include <string>
,它使您的代碼依賴於平台(即,它適用於GCC,但不適用於Visual C ++)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.