2016-05-14 146 views
3

我收到以下錯誤從地圖匹配的返回值的類型返回值

In file included from /Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:2: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:439: 
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:628: 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1673:31: error: no matching constructor for initialization of 'Vertex' 
      ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); 

這裏是我的代碼的相關部分的刪節版:

class Vertex { 
public: 
    int label; 
    vector<Vertex> adjacent_vertices; 
    Vertex(const int l) : label(l) { } 
    Vertex(const int l, vector<Vertex> adjacents) : label(l), adjacent_vertices(adjacents) { } 
    Vertex(const Vertex& other_vertex) : label(other_vertex.label), adjacent_vertices(other_vertex.adjacent_vertices){ } 
}; 
class Graph { 
public: 
    unordered_map<int, Vertex> vertices; 
    protected: 
    Vertex getmake_vertex(const int v) { 
     if (vertices.find(v) == vertices.end()) { 
      // not found, make new vertex 
      vertices[v] = Vertex(v); 
     } 
     return vertices[v]; 
    }; 
}; 

我已經確認運行此註釋掉的所有內容都會產生編譯器錯誤。有人可以向我解釋爲什麼會發生這種情況,以及我如何解決它? Here是具有完整編譯器輸出的要點。

回答

4

當您說vertices[v] = Vertex(v);時,它必須爲鍵v(賦值之前)創建一個Vertex,但Vertex沒有默認構造函數。

你應該用的是vertices.insert(make_pair(v, Vertex(v)))甚至vertices.emplace(v, Vertex(v))

這也適用於return vertices[v];。即使你和我知道在這個return語句被命中的時候,總是有一個v的值,但編譯器不會並且仍然必須生成代碼來潛在地創建一個,這會導致錯誤。

將其設置爲return vertices.find(v)->second;將修復該部分。沒有必要檢查並確保find的值不是end,因爲如果它不在那裏,我們就把它放進去。

+0

該方法的目的是創建頂點,如果它不存在,然後返回它。由於每個頂點都需要一個標籤,我該如何創建一個默認構造函數? –

+1

這確實是你怎麼做的,如果你的班級沒有默認的c'tor – haavee

+0

是的,沒關係。你仍然把它保存在你的'if(vertices.find(v)...)塊中 – xaxxon

0

如果我讀取錯誤消息的這部分是正確的,它需要一個默認構造函數Vertex;尤其是這樣的:

需要2個參數,但0分別提供

/Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:14:5: note: candidate constructor not viable: requires single argument 'l', but no arguments were provided 
    Vertex(const int l) : label(l) { } 
    ^
/Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:16:5: note: candidate constructor not viable: requires single argument 'other_vertex', but no arguments were provided 
    Vertex(const Vertex& other_vertex) : label(other_vertex.label), adjacent_vertices(other_vertex.adjacent_vertices){ } 
    ^
/Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:15:5: note: candidate constructor not viable: requires 2 arguments, but 0 were provided 
    Vertex(const int l, vector<Vertex> adjacents) : label(l), adjacent_vertices(adjacents) { } 
1

使用operator[]需要你的情況mapped_typeVertex)是缺省構造,因爲它插入一個默認 - 構造 mapped_type如果鍵不存在於地圖中。這是一個運行時間的決定,所以即使實際存在鍵,編譯時仍然需要默認構造函數。

在C++ 17,使用try_emplace

Vertex getmake_vertex(const int v) { 
    return vertices.try_emplace(v, v).first->second; 
} 

否則,使用insertemplace

Vertex getmake_vertex(const int v) { 
    return vertices.insert({v, v}).first->second; 
} 

(您可能需要使用Vertex(v)如果你做出Vertex(int)構造explicit,這你應該)

那些無實際插入鑰匙是否已在地圖上。所有三個 都返回pair<iterator, bool>,迭代器指向具有指定鍵的元素。


並不完全正確,但我們的目的真的不夠。