HashCompare の詳細

HashCompare の詳細#

独自のタイプに対して concurrent_hash_mapHashCompare 引数を機能させる方法はいくつかあります。

  • HashCompare 引数を明示的に指定する

  • HashCompare をデフォルトで tbb_hash_compare<Key> に設定し、次のいずれかを実行します。

    • テンプレート tbb_hash_compare<Key> の特殊化を定義します。

例えば、Foo タイプのキーがあり、Foo に対して operator== が定義されている場合、次に示すように tbb_hasher を定義する必要があります。

size_t tbb_hasher(const Foo& f) { 
    size_t h = ...compute hash code for f... 
    return h; 
};

一般に、tbb_hash_compare<Key> または HashCompare の定義では、次の 2 つのシグネチャーを提供する必要があります。

  • Keysize_t にマッピングする hash メソッド

  • 2 つのキーが等しいか判定する equal メソッド

2 つのキーが等しい場合、それらは同じ値にハッシュされる必要があるため、シグネチャーは 1 つのクラスにまとめられます。そうしないとハッシュテーブルが機能しない可能性があります。常に 0 にハッシュすればこの要件を満たすことができますが、非常に効率が悪くなります。各キーが異なる値にハッシュされるのが理想的です。少なくとも、2つの別のキーが同じ値にハッシュされる可能性を低くしておく必要があります。

異なるインスタンスで異なる動作が必要でなければ、HashCompare のメソッドは static です。その場合、HashCompare をパラメーターとして受け取るコンストラクターを使用して、concurrent_hash_map を構築します。次の例は、インスタンス依存のメソッドを使用した前の例のバリエーションです。インスタンスは、内部フラグ ignore_case に基づいて、大文字/小文字を区別するハッシュまたは区別しないハッシュ、および比較の両方を実行します。

// ハッシュと比較演算を定義する構造 
class VariantHashCompare { 
    // true の場合、大文字と小文字は無視されます。 
    bool ignore_case; 
public: 
    size_t hash(const string& x) const { 
        size_t h = 0; 
        for(const char* s = x.c_str(); *s; s++) 
            h = (h*16777179)^*(ignore_case?tolower(*s):*s); 
        return h; 
    } 
    // 文字列が等しい場合は True 
    bool equal(const string& x, const string& y) const { 
        if( ignore_case ) 
            strcasecmp(x.c_str(), y.c_str())==0; 
        else 
            return x==y; 
    } 
    VariantHashCompare(bool ignore_case_) : ignore_case(ignore_case_) {} 
}; 

typedef concurrent_hash_map<string,int, VariantHashCompare> VariantStringTable; 

VariantStringTable CaseSensitiveTable(VariantHashCompare(false)); 
VariantStringTable CaseInsensitiveTable(VariantHashCompare(true));