// encoding: Shift_JIS //////////////////////////////////////////////////////////////////// // // アイデア源は // http://article.gmane.org/gmane.comp.lib.boost.devel/20885 // これ。型 R (Cls::)(P1,P2) のメンバ関数から型 R (Cls*,P1,P2) の // 普通の関数を自動生成、といったもので、私のこのソースと違って // いたってマトモな話題です。 // //////////////////////////////////////////////////////////////////// namespace { namespace detail { template struct ClassInfoHolder { private: template struct MemFunHolder { static Cls* ptr; static R fun() { return (ptr->*mf)(); } }; public: template static R (*getfun(Cls& obj))() { MemFunHolder::ptr = &obj; return &MemFunHolder::fun; } }; template template Cls* ClassInfoHolder::MemFunHolder::ptr = 0; template ClassInfoHolder helper( R (Cls::*)() ) { return ClassInfoHolder(); } }} #define true_mem_fun(MF,OBJ) detail::helper<__LINE__>(MF).getfun(OBJ) //////////////////////////////////////////////////////////////////// // // ...とまあ、この__LINE__がトリック。欲しい目的のためには // インスタンス一つにつき一つの関数を作らなきゃいけないのですが、 // ここでは無名namespaceと組み合わせて、"疑似"唯一性を実現してます。 // つまり一行で2回 true_mem_fun() を書いたら破綻します。^^; // // これを避けるには__LINE__の代わりにid_counter<> // http://pc2.2ch.net/tech/kako/1037/10377/1037795348.html 107- // などを使うとベターかもしれません。 // // が、いずれにせよ、「インスタンス一つにつき」ではなく // 「ソース上での一箇所につき」一つの関数しか作れないので、 // 本当の意味で「メンバ関数からthisをbind済みの普通の関数を作る」 // のはこの方法では不可能です。 // // あくまでネタなのでご注意を。^^ // //////////////////////////////////////////////////////////////////// #include using namespace std; struct Test { int x; void ShowX() { cout << x << endl; } }; int main() { Test t1, t2; void (*f)() = true_mem_fun(&Test::ShowX, t1); void (*g)() = true_mem_fun(&Test::ShowX, t2); t1.x = 1, t2.x = 2; f(); g(); t1.x = 3, t2.x = 4; f(); g(); }