2009-08-25 17 views
6

どのように私はハッシュすることができます(std :: tr1 :: hashまたはboost :: hash)C++ポインタのメンバ関数へのポインタ?メンバ関数へのポインタをハッシュして比較する方法は?

例:

私はクラスのクラスのいくつかのdiferent方法にはいくつかのBOOL(クラス:: * functionPointer)()(静的でない)、その点を持っていると私はそれらへのポインタメンバ関数をハッシュする必要があります。

どうすればいいですか?

また、(std :: less)それらのメンバ関数ポインタを比較して、std :: setに格納することができますか?

+7

通常、アクセスするものを指すので、ポインタをハッシュする理由はありません。あなたが何を求めているかを示すコードを提供してください。 –

+0

1つの関数ポインタが別のポインタよりも「少ない」と言うのはいつですか? –

+0

@bojan:比較の唯一の目的はソートされたリストにそれらを格納することだけであれば、確定的な順序付けができます。たとえば、バイナリ値。 – erikkallen

答えて

13

メンバー関数へのポインタを含む、すべてのC++オブジェクトは、charの配列としてメモリ内に表されます。だから、試みることができる:

bool (Class::*fn_ptr)() = &Class::whatever; 
const char *ptrptr = static_cast<const char*>(static_cast<const void*>(&fn_ptr)); 

を今すぐ(sizeof(bool (Class::*)()))バイトの配列、およびハッシュを指すようptrptrを治療またはそれらのバイトを比較します。必要に応じて、charの代わりにunsigned charを使用できます。

C++ 03では、メンバ関数へのポインタがPODであり、memcpyを使用してコピーすることができます。これは、同じbyte-for-byte値を持つ場合、それらが同じであることを意味します。

問題は、メンバー関数ポインタの記憶表現に値に関与しないビットが含まれている可能性があるため、同じメンバ関数への異なるポインタで必ずしも同じであるとは限りません。あるいは、ある種の理由でコンパイラが同じクラスの同じ関数を指し示す複数の方法を持っているかもしれません。これらの方法はバイトワイズではありません。いずれにせよ、あなたは偽陰性を得ることができます。実際にメンバー関数ポインタが実際にどのように実装されているかを調べる必要があります。何らかの形でメンバー関数ポインタのためにoperator==を実装しなければなりません。そして、あなたがどのようにして順序とハッシュ関数を見つけ出すことができるかを知ることができるならば。

これは潜在的に難しいです:メンバ関数ポインタは扱いにくく、どの種類の関数が指し示されているか(仮想、継承されている)に応じて、ストレージには非参加の "余裕空間"の異なる量が含まれている可能性があります。したがって、おそらく、コンパイラの実装の詳細とかなり大きく対話する必要があります。 http://www.codeproject.com/KB/cpp/FastDelegate.aspx

より洗練された選択肢は、すべての関数ポインタを「標準化」するために、配列を使用して線形検索を行い、次に、「標準」の位置に基づいて比較およびハッシュを行うことです。配列内のその関数ポインタのインスタンスあなたのパフォーマンス要件が何であるかによって異なります。また、要件があっても、クラス(およびその派生クラス)には線形検索で長時間かかるような多くの関数がありますか?

typedef bool (Class::*func)(); 
vector<func> canon; 

size_t getIndexOf(func fn_ptr) { 
    vector<func>::iterator it = find(canon.begin(), canon.end(), fn_ptr); 
    if (it != canon.end()) return it - canon.begin(); 
    canon.push_back(func); 
    return canon.size() - 1; 
} 
+0

ありがとうchar *トリックを行う! 私のコンパイラでのみ、static_castではなくreinterpret_castが必要です。 – AllDayCpp

+1

厄介な問題の優れた治療法、+1。 pmf1 == pmf2は、必ずしもビット単位の同一性を意味するものではないということは私には起こりませんでした。 –

+0

メンバ関数へのポインタにはパディングが含まれている可能性があります。パディングは等しいかどうかを比較するときに無視され、ランダムな値をとります。パディングバイトをハッシュすると、ハッシュ関数が失敗します。 –

0

前の回答で説明したように、私は(マイクロソフトコンパイラ2010年)のポインタをキャストことができませんでしたが、これは私の作品:

static string fmptostr(int atype::*opt) 
    { 
     char buf[sizeof(opt)]; 
     memcpy(&buf,&opt,sizeof(opt)); 
     return string(buf,sizeof(opt)); 
    } 

ポインタのビット単位の身元については、それはそれようビット単位することができます適切なコンパイラスイッチが使用されているようです。少なくともこれはマイクロソフトコンパイラの場合、 #pragma pointers_to_members とswitch .../vmgを使用しています。

関連する問題