HashCompare の詳細#
独自のタイプに対して concurrent_hash_map の HashCompare 引数を機能させる方法はいくつかあります。
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 つのシグネチャーを提供する必要があります。
Keyをsize_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));