问题描述
我有以下Graph类:
void MaterialPop::add(std::string name,std::shared_ptr<MaterialArch> mat){
std::cout << "ADD : "<<name << std::endl;
bool alreadyExist = false;
for (auto var : m_varMaterials) {
if(var.second == mat){
alreadyExist = true;
}
}
if(!alreadyExist){
m_console->addMatName(name);
m_varMaterials.emplace(name,std::move(mat));
m_views.emplace(name,std::make_shared<MaterialArchView>(m_varMaterials.at(name)));
m_visibility.emplace(name,true);
}
}
当我想使用默认构造函数构造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();
}
。我应该如何更改代码才能使用Graph的默认构造函数?
解决方法
unordered_map
中的 Key 必须是可哈希的。通过添加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
如果您想保留Edge
private
,则使用函子可能会更容易。这是一个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();
}