Проблемы с unordered_map

0

Я пытаюсь реализовать различные структуры данных и алгоритмы для обучения.

На данный момент я пытаюсь реализовать шаблон класса Graph, но у меня возникают проблемы с попыткой использовать STL unordered_map (и, consequently priority_queue в будущем).

В основном, что происходит на данный момент, по некоторым причинам типы шаблонов не совпадают при попытке инициализировать карту вершин внутри графика. Из того, что я понимаю, поскольку я только планирую использовать ключевые типы из родных типов C++, пока мой тип значения является указателем, мне не нужно делать какую-либо дополнительную работу отдельно от конструктора копирования для моего пользовательского класса вершин, По умолчанию для сравнения/хэширования должно быть достаточно. Но это не так, и ошибка, которую я получаю, является непонятной.

Ошибка:

Error   1   error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::unordered_map<T,graph<T>::vertex *,std::hash<int>,std::equal_to<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' (or there is no acceptable conversion)

Код:

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <unordered_map>
#include <numeric>
#include <functional>

using namespace std;
class vertex;
template <class T>
class graph {
public:

graph() { verts = unordered_map<T, vertex*>(); }
~graph() {
    for each(auto v in verts)
        delete(v);
    delete(verts); 
}
private:
unordered_map<T, vertex*> verts;

// --- Inner Classes ---

struct path {
    vertex *dest;
    double cost;

    path(vertex *d = nullptr, double c = 0.0) : dest(d) : cost(c) {}

    inline int compare(const path& p) {
        auto other = p.cost;

        return cost < other ? -1 :
            cost > other ? 1 : 0;
    }
};

struct edge {
    vertex *dest;
    double cost;

    edge(vertex *d = nullptr, double c = 0.0) : dest(d) : cost(c) {}
};

class vertex {
public:
    // Vertex relationships
    T name;
    vector<edge>* adj;

    // Path Finding Information
    double distance;
    vertex *prev;
    int scratch;

    void reset_path_finding() {
        distance = double.infinity();
        prev = nullptr;
        scratch = 0;
    }

    vertex(T name = default(T)) : name(name) : adj(new vector<edge>) : 
        distance(double.infinity()) : prev(nullptr) : scratch(0) {}
    vertex(const vertex& v) {
        name = v.name;
        adj = v.adj;
        distance = v.distance;
        prev = v.prev;
        scratch = v.scratch;
    }
    ~vertex() { delete(adj); }
private:
};
};

int main()
{
graph<int> myGraph = graph<int>();

cout << "Press any key to continue..." << endl;
int x;
cin >> x;
return 0;
}
  • 0
    Можете ли вы указать строку в источнике, о котором ошибка?
  • 1
    Кстати, когда вы объявляете переменную (член класса, локальную или глобальную), например, локальный myGraph в main функции или verts в классе graph , вам не нужно инициализировать, как вы это делаете. Просто объявив это будет достаточно.
Теги:
class
graph
map

1 ответ

3
Лучший ответ

Первая проблема заключается в том, что перед объявлением его вы используете graph::vertex вложенного класса graph::vertex. Дальнейшая путаница вызвана тем, что вы объявили class vertex вне graph, поэтому компилятор изначально думает, что вы имеете в виду этот класс. Вы можете объявить vertex около начала graph:

template <class T>
class graph {
    class vertex;
private:
    // and so on
};

Существует еще несколько синтаксических ошибок, которые должны быть очевидны, если вы посмотрите на строки, на которые ссылаются сообщения об ошибках. Синтаксис для цикла, основанного на диапазоне, равен

for (auto v : verts)  // not for each(auto v in verts)

Это дает вам пары ключ-значение, поэтому для удаления vertex вам нужно

delete v.second;

Еще лучше измените verts в unordered_map<T, vertex>, содержащий объекты, а не указатели, и автоматически будет управлять всей своей памятью - вам вообще не понадобится деструктор.

Синтаксис для инициализируемого значения временного

T()  // not default(T)

Классы в списке инициализаторов конструктора разделяются запятыми, а не двоеточиями:

path(vertex *d = nullptr, double c = 0.0) : dest(d) , cost(c) {}
                                                    ^ not :

double с бесконечным значением

std::numeric_limits<double>::infinity() // not double.infinity()

для которых вам необходимо включить <limits>.

verts не нужно удалять в деструкторе, так как вы его не new. Также не нужно назначать из созданного по умолчанию временного элемента в конструкторе, поскольку он просто был сконфигурирован по умолчанию.

Есть несколько мест, где вы делаете жизнь трудной для себя, используя излишнее использование указателей и new. Старайтесь избегать new кроме случаев, когда вам это действительно нужно; и узнайте об RAII, особенно о использовании интеллектуальных указателей и контейнеров, когда вы это сделаете.

  • 0
    Вау, спасибо. Я собираюсь отказаться от этого кода и сделаю это снова завтра с этим отзывом. У меня было достаточно возни, пытаясь заставить его работать. Но многие из тех вещей, на которые вы указываете, даже не появлялись как сообщения об ошибках, когда я пытаюсь скомпилировать этот класс в целом. (MS C ++) Если я не приведу это в main как небольшой тестовый фрагмент, а иногда даже не тогда. Например, неправильный для каждого синтаксиса компилируется и ведет себя как ожидалось. Я загружаю Clang на этот новый компьютер, но, поскольку я живу в сельской местности, загрузка занимает некоторое время.
  • 0
    @MorphingDragon: Так как это шаблон, многие ошибки не будут обнаружены, если не будет создан экземпляр функции или класса, в котором они находятся, - что (обычно) не произойдет, если программа его не использует. Попробуйте создать большие классы, добавляя за один раз небольшую функциональность, по мере написания тестов, чтобы не потерять огромную кучу ошибок, которые нужно будет пролистать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню