クラスがあるとしますX
:
class X {
// ...
size_t hash() const { return ...; }
};
としてstd::tr1::unordered_map<X, int, HashFn>
渡したい場所を
作成したいと思います。独自のファンクター オブジェクトを宣言できることはわかっています。へのポインタを直接渡すことでこれを行う方法があるはずだと思います。X::hash()
HashFn
X::hash()
ある?
クラスがあるとしますX
:
class X {
// ...
size_t hash() const { return ...; }
};
としてstd::tr1::unordered_map<X, int, HashFn>
渡したい場所を
作成したいと思います。独自のファンクター オブジェクトを宣言できることはわかっています。へのポインタを直接渡すことでこれを行う方法があるはずだと思います。X::hash()
HashFn
X::hash()
ある?
いいえ; あなたがそれを示したように、あなたは小さなユーティリティ構造体を必要とします:
#include <functional>
template<typename T, std::size_t (T::*HashFunc)() const = &T::hash>
struct hasher : std::unary_function<T, std::size_t>
{
std::size_t operator ()(T const& t) const
{
return (t.*HashFunc)();
}
};
unordered_map
次に、次のように作成できます。
std::tr1::unordered_map<X, int, hasher<X> > m;
いいえ、ありません。その理由は、HashFn として使用されるものはすべて、コンテナー内のオブジェクトへの const 参照である単一の引数を取る必要があるためです。 コンテナー内のオブジェクトへのconstポインターX::hash
である単一の引数を取るため(この場合、ポインターは暗黙的な最初の引数です)、その関数を単独で使用することはできません。this
おそらく、boost::lambda と boost::bind を使用してバインド マジックを使用します。正確な方法はわかりませんが、おそらく次のようになります。
boost::bind(&X::hash, &_1);
X::hash をポインターで呼び出す関数オブジェクトを作成します。
size_t hash() const { return ...;}
ハッシュ値を計算Key
する関数は、関数がとらない型のパラメーターを 1 つ受け取ります。したがって、その署名はそもそも間違っています。
ファンクターではなく関数を実装したいので、次のようにします。
size_t hash(const KeyType &key)
{
return /*calculate hash and return it*/;
}
それをstatic
メンバー関数にして渡すX::hash
か、フリー関数にするかはあなたの選択です。
直接はできませんが、ラップすることはできます。これを行う簡単な方法はboost::mem_fn()
、またはコンパイラがサポートしている場合は標準の同等物を使用することです: tr1::mem_fn()
(TR1 から) またはstd::mem_fn()
(C++11 から)。
編集:実際にはそれほど単純ではありません。mem_fn()
関数パラメーターに対しては問題なく機能しますが、戻り値の型が指定されていないため、テンプレート パラメーターとして使用するのは困難です。C++11 をサポートしている場合はdecltype
、型を見つけるために使用できます。それ以外の場合は、あなたが述べたように、独自の関数オブジェクトを作成することをお勧めします。