我正在编写一个哈希仿函数,用于boost::unordered_map
,它将存储boost::graph
边缘描述符。很简单。无向和有向图形边缘必须以不同方式进行散列(至少在我的情况下,边缘(u,v)
和(v,u)
在图表未定向时是等效的,因此map[(u,v)]
和map[(v,u)]
必须指向相同的值)。我可以使用图形特征类(boost::graph_traits<Graph>::directed_category
)检测定向性,但是如何使用模板定义不同的实现?
以下是我到目前为止所做的,但我不想要if
条款。相反,我希望EdgeHash
根据operator()
的值编译directed_category
的不同版本。如何实现这一目标?
template <typename Graph>
struct EdgeHash {
typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
std::size_t operator()(const Edge& e) const {
std::size_t hash = 0;
if(boost::is_same<boost::graph_traits<Graph>::directed_category, boost::directed_tag>::value) {
boost::hash_combine(hash, e.m_source);
boost::hash_combine(hash, e.m_target);
} else {
boost::hash_combine(hash, std::min(e.m_source, e.m_target));
boost::hash_combine(hash, std::max(e.m_source, e.m_target));
}
return hash;
}
};
答案 0 :(得分:1)
使用boost::enable_if
,您可以执行此操作,但是,您必须专门化结构。例如(未经测试)
template <typename Graph, class Enable = void>
struct EdgeHash {
typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
std::size_t operator()(const Edge& e) const {
std::size_t hash = 0;
boost::hash_combine(hash, std::min(e.m_source, e.m_target));
boost::hash_combine(hash, std::max(e.m_source, e.m_target));
return hash;
}
};
template <typename Graph>
struct EdgeHash<Graph, typename boost::enable_if<boost::is_same<boost::graph_traits<Graph>::directed_category, boost::directed_tag> >::type>
{
typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
std::size_t operator()(const Edge& e) const {
std::size_t hash = 0;
boost::hash_combine(hash, e.m_source);
boost::hash_combine(hash, e.m_target);
return hash;
}
};
答案 1 :(得分:1)
可能在实际的EdgeHash类中添加一个bool模板参数?例如:
template <typename Graph, bool is_directed>
struct EdgeHashImpl {
typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
std::size_t operator()(const Edge& e) const {
std::size_t hash = 0;
boost::hash_combine(hash, e.m_source);
boost::hash_combine(hash, e.m_target);
return hash;
}
};
template <typename Graph>
struct EdgeHashImpl <Graph, false>
{
typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
std::size_t operator()(const Edge& e) const {
std::size_t hash = 0;
boost::hash_combine(hash, std::min(e.m_source, e.m_target));
boost::hash_combine(hash, std::max(e.m_source, e.m_target));
return hash;
}
};
template <typename Graph>
struct EdgeHash
: public EdgeHashImpl
<Graph, boost::is_same<boost::graph_traits<Graph>::directed_category, boost::directed_tag>::value)>
{};
答案 2 :(得分:1)
将散列放在一个单独的结构中,该结构模板化为定向类别类型。
template<typename Directed, typename Edge>
struct Hasher {
static std::size_t edge_hash(const Edge& e) {
std::size_t hash = 0;
boost::hash_combine(hash, e.m_source);
boost::hash_combine(hash, e.m_target);
return hash;
}
};
template<typename Edge>
struct Hasher<boost::directed_tag, Edge> {
static std::size_t edge_hash(const Edge& e) {
std::size_t hash = 0;
boost::hash_combine(hash, std::min(e.m_source, e.m_target));
boost::hash_combine(hash, std::max(e.m_source, e.m_target));
return hash;
}
};
template <typename Graph>
struct EdgeHash {
typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
std::size_t operator()(const Edge& e) const {
return Hasher<
boost::graph_traits<Graph>::directed_category,
Edge>::edge_hash(e);
}
};