関数ポインタ、あるいはそれをテンプレートの特殊化で捌く時用のメモ
鳥頭化がひどいのでメモっておこうって。
結論として
- function_traitsの特殊化で、「R_(Arg_)」と「R_(*)(Arg_)」は区別され、それはdecltype(hoge)なのかdecltype(&hoge)なのかに依る
- typeid関数に対しても&を付けてhoge関数を渡すか渡さないかで、void (__cdecl*)(int)となるかvoid (__cdecl)(int)となるかが別れる(上の話と整合的)
- 関数ポインタに関数を渡す時は6つけてもつけなくてもいいし、その関数ポインタから関数を実行する時も、*を付けてもつけなくてもいい
ってところかな。
#include<iostream> //オレオレfunction traits template<typename T_> struct function_traits; template<typename R_, typename Arg_> struct function_traits<R_(Arg_)> { typedef Arg_ argument; static const int X = 1; }; template<typename R_, typename Arg_> struct function_traits<R_(*)(Arg_)> { typedef Arg_ argument; static const int X = 333; }; //適当な関数 void hoge(int x){ std::cout << "I'm hoge" << std::endl; } //Main int main() { std::cout << "hogeに対するtypeidの適用結果" << std::endl; std::cout << "hogeのtypeid" << std::endl; std::cout << typeid(hoge).name() << std::endl; std::cout << "&hogeのtypeid" << std::endl; std::cout << typeid(&hoge).name() << std::endl; std::cout << "*hogeのtypeid" << std::endl; std::cout << typeid(*hoge).name() << std::endl; std::cout << std::endl; std::cout << "function_traitsのR_(Arg_)=1に特殊化されるか、それともR_(*)(Arg_)=333となるか" << std::endl; std::cout << "hogeの場合" << std::endl; std::cout << function_traits<decltype(hoge)>::X << std::endl; std::cout << "&hogeの場合" << std::endl; std::cout << function_traits<decltype(&hoge)>::X << std::endl; std::cout << "*hogeの場合" << std::endl; std::cout << function_traits<decltype(*hoge)>::X << std::endl; std::cout << std::endl; std::cout << "関数ポインタの復習的なもん" << std::endl; //適当にtypdef typedef void(*Func)(int); //typedef void(Gunc)(int); は当然だめ //&つけてもつけなくてもOKぽい Func f = hoge; Func g = &hoge; //*つけてもつけなくてもOKぽい f(1); (*g)(1); return 0; }
実行結果
hogeに対するtypeidの適用結果 hogeのtypeid void __cdecl(int) &hogeのtypeid void (__cdecl*)(int) *hogeのtypeid void __cdecl(int) function_traitsのR_(Arg_)=1に特殊化されるか、それともR_(*)(Arg_)=333となるか hogeの場合 1 &hogeの場合 333 *hogeの場合 1 関数ポインタの復習的なもん I'm hoge I'm hoge