显式默认的默认构造函数被隐式删除,因为 unordered_map 与结构一起用作键

Dan*_*iel 0 c++ unordered-map default-constructor

我有以下 Graph 类:

class Graph {
private:
    struct Edge {
        string vertex1{}, vertex2{};
        int val{};

        Edge() = default;
        ~Edge() = default;
        explicit Edge(string v1, string v2, int value) : vertex1(std::move(v1)), vertex2(std::move(v2)), val(value) {};
        bool operator==(const Edge&) const;
    };

    unordered_map<Edge, Edge*> edges;

public:
    Graph() = default;
    ~Graph();
}
Run Code Online (Sandbox Code Playgroud)

当我想用默认构造函数构造一个 Graph 时,它说Explicitly defaulted default constructor of 'Graph' is implicitly deleted because field 'edges' has a deleted default constructor. 我应该如何更改我的代码,以便能够使用 Graph 的默认构造函数?

Ted*_*gmo 6

密钥unordered_map需要被哈希的。通过添加std::hash类模板的特化或在创建unordered_map.

您没有证明您已经进行了std::hash<Edge>专业化,并且您没有unordered_map使用函子创建来进行散列,这就是默认构造失败的原因。

要添加std::hash<Edge>专业化,您可以这样做(如果您Edge公开):

namespace std {

template<>
struct hash<Graph::Edge> {
    size_t operator()(const Graph::Edge& e) const {
        size_t hash_result;
        // calculate the hash result
        return hash_result;
    }
};

} // namespace std
Run Code Online (Sandbox Code Playgroud)

如果您想保留Edge private,使用函子可能会更容易。这是一个 a 形式的示例,struct它使unordered_map默认构造变得可构造:

class Graph {
private:
    struct Edge {
        // ...
    };

    // the hashing functor:
    struct edge_hasher {
        size_t operator()(const Edge& e) const {
            // an example implementation using boost::hash_combine
            // from <boost/container_hash/hash.hpp>:
            std::hash<std::string> h;
            size_t hash_result = 0;
            boost::hash_combine(hash_result, h(e.vertex1));
            boost::hash_combine(hash_result, h(e.vertex2));
            boost::hash_combine(hash_result, std::hash<int>{}(e.val));
            return hash_result;
        }
    };

    std::unordered_map<Edge, Edge*, edge_hasher> edges; // <- hasher included

public:
    Graph() = default;
    ~Graph();
}
Run Code Online (Sandbox Code Playgroud)