按特征类专门化函数

发布于 2024-12-01 04:48:52 字数 1106 浏览 2 评论 0原文

我正在编写一个哈希函子,用于 boost::unordered_map ,它将存储 boost::graph 边缘描述符。够简单的。然而,无向图和有向图边必须以不同的方式进行散列(至少在我的情况下,当图为无向,因此 map[(u,v)]map[(v,u)] 必须指向相同的值)。我可以使用图形特征类 (boost::graph_traits::directed_category) 检测方向性,但是如何使用模板定义不同的实现呢?

下面是我到目前为止所得到的,但我不需要 if 子句。相反,我希望 EdgeHash 根据 directed_category 的值编译不同版本的 operator() 。如何才能实现这一目标?

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;
    }
};

I'm writing a hash functor for use in a boost::unordered_map which will store boost::graph edge descriptors. Simple enough. Undirected and directed graph edges must be hashed differently however (at least in my case, the edges (u,v) and (v,u) are equivalent when the graph is undirected, so map[(u,v)] and map[(v,u)] must point at the same value). I can detect directedness with the graph traits class (boost::graph_traits<Graph>::directed_category), but how can I define different implementations using templates?

Below is what I've got so far, but I don't want the if clause. Instead I want EdgeHash to compiles different versions of operator() depending on the value of directed_category. How can this be achieved?

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;
    }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

满意归宿 2024-12-08 04:48:53

也许在实际的 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)>
{};

Maybe adding one bool template parameter in the actual EdgeHash class? For instance:

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)>
{};
赠意 2024-12-08 04:48:52

将哈希放入以定向类别类型为模板的单独结构中。

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);
    }
};

Put hashing in a separate struct templated on directed category type.

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);
    }
};
柒夜笙歌凉 2024-12-08 04:48:52

使用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;
    }
};

Using boost::enable_if, you can do this, however, you have to specialize the structure. e.g (untested)

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;
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文