2012-01-01 60 views
10

我努力做到以下幾點:如何使升壓unordered_map支持輕量級<string>

boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> > map; 

     boost::flyweight<std::string> foo(name); 
     map[foo] = foo; 

但是編譯器會抱怨: 「錯誤C2665:‘提高:: HASH_VALUE’:沒有17個重載的可能轉換所有參數類型「。

但我已經定義了以下功能:

std::size_t hash_value(const boost::flyweight<std::string> & b) 
{ 
    boost::hash<std::string> hasher; 
    const std::string & str = b.get(); 
    return hasher(str); 
} 
bool operator==(const boost::flyweight<std::string>& f, const boost::flyweight<std::string> & second) 
{ 
    return f.get() == second.get(); 
} 

但doesn't編譯。

我需要做些什麼來提高unordered_map以支持flyweight?

[編輯] 我把它用下面的代碼工作:

struct flyweight_hash 
    { 
     std::size_t operator()(const boost::flyweight<std::string> &elm) const 
     { 
      boost::hash<std::string> hasher; 
      const std::string & str = elm.get(); 
      return hasher(str); 
     } 
    }; 

,並通過它作爲一個模板參數的圖譜的構建:

boost::unordered_map<boost::flyweight<std::string>, boost::flyweight<std::string> , flyweight_hash > map; 

在這種情況下,我不明白重載hash_value的方式沒有奏效。

回答

7

boost::hash通過參數相關查找(ADL)調用hash_value。您正試圖爲命名空間boost中的類定義hash_value函數。因此你的hash_value函數也需要進入這個命名空間,ADL才能工作。不幸的是,將函數添加到外部命名空間是相當邪惡的,應該避免。您使用自定義哈希的解決方案似乎很好。

一個小例子代碼來說明:

namespace boost { 
    // somewhere in boost 
    template<typename T> 
    std::size_t hash(const T& t) { 
    // call using ADL 
    // e.g. if called with object of class type foo::bar this will 
    // pick up foo::hash_value despite the lack of namespace 
    // qualification 
    return hash_value(t); 
    } 
} 

// your hash_value (presumably in the global namespace) 
// not picked up by above call 
std::size_t hash_value(boost::flyweight<T>...); 

namespace boost { 
    // this would be picked up but is slightly evil 
    std::size_t hash_value(boost::flyweight<T>...); 
} 
+0

這只是不好的,因爲'boost :: unordered_map'的默認哈希似乎並沒有通過boost :: hash_value觸發ADL;返回hash_value(key);'。儘管我現在無法檢查。 – Xeo 2012-01-01 21:34:51

+0

@Xeo默認的hasher應該是'boost :: hash',而不應該是'unordered_map'特有的。至少文件是這樣說的。 – pmr 2012-01-01 21:47:53

+0

當然,但這並不會改變ADL啓用的調用似乎沒有被使用。 – Xeo 2012-01-01 21:49:44

5

這是哈希的東西已經被散列可惜。 Flyweight保留相同對象的單個實例,因此散列此實例的地址而不是其內容的效率更高。我做如下(以std,而不是在boost,因爲我使用C++ 11,所以我延長std::hash,不boost::hash):

namespace std 
{ 
    template <typename T> 
    struct hash<boost::flyweight<T, boost::flyweights::no_tracking>> 
    { 
    using value_type = boost::flyweight<T, boost::flyweights::no_tracking>; 
    size_t operator()(const value_type& ss) const 
    { 
     hash<const void*> hasher; 
     return hasher(&ss.get()); 
    } 
    }; 
} 

我已經證實,這個工程設計,不是偶然的:http://lists.boost.org/boost-users/2013/03/78007.php