2011-08-24 5 views
3

boost::unordered_map에 사용하기 위해 해시 펑터를 작성 중이며 boost::graph 에지 설명자가 저장됩니다. 충분히 간단합니다. 방향이 지정되지 않은 그래프 에지는 다르게 해시되어야합니다 (최소한 제 경우에는 그래프가 무향 인 경우 (u,v)(v,u)이 동일하므로 map[(u,v)]map[(v,u)]은 같은 값을 가리켜 야합니다). 그래프 특성 클래스 (boost::graph_traits<Graph>::directed_category)로 직접성을 감지 할 수 있지만 템플릿을 사용하여 다른 구현을 어떻게 정의 할 수 있습니까?특징 클래스에 의한 특수화 함수

아래는 내가 지금까지 가지고 있지만, 나는 if 절을 원하지 않습니다. 대신 EdgeHashdirected_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; 
    } 
}; 

답변

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

코드에 몇 가지 오류가 있습니다. 잊혀진'typename'은 일반적인'Hasher'에서'operator()'에서'edge_hash'를 호출하지 않고, 역 논리 (다른 한편에서는 제 잘못이 될 수도 있습니다 ...). 그러나 그것을 고치면 효과가 있습니다. 고맙습니다! – carlpett

+0

고정. 또한 Hasher는 유틸리티 유형이므로 숨기려고 할 수 있습니다. EdgeHash의 private 중첩 (멤버) 클래스로 만듭니다. – AndrzejJ

+0

좋습니다! 나는 익명의 네임 스페이스에 넣었으므로 문제는되지 않는다. :) – carlpett

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

실제 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)> 
{}; 
관련 문제