2016-05-14 3 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]; 
    }; 
}; 

I подтвердили, что выполнение этого с учетом всего остального вызывает ошибку компилятора. Может кто-нибудь объяснить мне, почему это происходит и как я могу это исправить? Here - это совокупность с полным выходом компилятора.

ответ

4

Когда вы говорите vertices[v] = Vertex(v); он должен создать Vertex для ключа v (до назначения), но Vertex имеет конструктора по умолчанию.

То, что вы должны использовать это vertices.insert(make_pair(v, Vertex(v))) или даже vertices.emplace(v, Vertex(v))

Это также относится и к return vertices[v];. Несмотря на то, что мы с вами знаем, что к моменту появления этого оператора возврата всегда есть значение для v, компилятор не должен и должен генерировать код, чтобы потенциально сделать его, и это вызывает ошибку.

Установка на return vertices.find(v)->second; исправит эту часть. Не нужно проверять и удостоверяться, что значение find не end, так как мы просто положили его, если его там не было.

+0

Метод предназначен для создания вершины, если она еще не существует, а затем возвращает ее. И так как каждой вершине нужна метка, как мне создать конструктор по умолчанию? –

+1

Это действительно то, как вы это делаете, если ваш класс не имеет по умолчанию c'tor – haavee

+0

Да, это нормально. Вы все еще держите его внутри своего 'if (vertices.find (v) ...)' block – 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_type (Vertex) в вашем случае, чтобы быть по умолчанию конструктивны , потому что он вставляет значение по умолчанию -constructed mapped_type если на карте нет ключа. Это решение во время выполнения, поэтому даже если ключ действительно существует, вам все равно нужен конструктор по умолчанию во время компиляции.

В C++ 17, используйте try_emplace:

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

В противном случае, используйте insert или emplace.

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

(Вы, возможно, потребуется использовать Vertex(v), если вы сделаете Vertex(int) конструктор explicit, который вы, вероятно, следует.)

Ни один из тех, кто на самом деле не вставляет, если ключ уже в карте. Все три возвращают pair<iterator, bool> с итератором, указывающим на элемент с указанным ключом.


Не совсем верно, но достаточно верно и для наших целей.

Смежные вопросы