2012-01-01 9 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コンパイル。

flyweightをサポートするためにboost unordered_mapを行うには何が必要ですか?

[EDIT] 私は次のコードで動作するようにそれを得た:

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; 

I 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をトリガーしていないようです。 return hash_value(key); '。私は今それを確認することはできません。 – Xeo

+0

@Xeoデフォルトのハッシャーは 'boost :: hash'でなければならず、' unordered_map'に特有であってはなりません。少なくともドクターはそう言います。 – pmr

+0

もちろん、ADL対応の通話は使用されていないようには変わりません。 – Xeo

5

すでにハッシュ化されたものをハッシュする残念です。 Flyweightは等しいオブジェクトの単一のインスタンスを保持するので、コンテンツではなくこのインスタンスのアドレスをハッシュする方が効率的です。 (私はC++ 11を使用していて、ないboostで、stdで、私はboost::hashを、std::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

関連する問題