meta-daouble - コンパイル時浮動少数
id:Cryoliteさんとこに面白そうな話題みっけ。
http://d.hatena.ne.jp/Cryolite/20050621
さすがにBoostML追うほどの時間はないので
深く間で掘り下げることはできないですが
以前に多倍長整数をやったときにdouble型を
即値でぶっこめないかなぁと思ってました。
探してみるとdoubleの符号、指数、仮数をintで
メタっぽくやってるクラスライブラリは見つけられたんですが
あんまり気軽にはつかえない感じでした。
そこで、そのときに考えたネタのお披露目。
intならテンプレートで渡せるのにdoubleは無理だから
クラスに包み込んでテンプレートにしちゃおうという
誰でも思いつくような簡単な仕組みです。
データを保持する部分は、intならテンプレート非型やEnumHackなんでしょうけど
doubleの場合はインライン関数ってのがポイントです。
ほんと簡単なのですが、値ごとにクラスを作らないといけないのが面倒くさいです。
あと可読性も微妙です。マクロとか使えば多少マシになるでしょうけど。
んで、肝心のソース。
struct PI { static double Value() { return 3.14; } }; struct Double { static double Value() { return 5.0; } }; template <typename Left,typename Right> struct Mul { static double Value() { return Left::Value()*Right::Value(); } }; int _tmain(int argc, _TCHAR* argv[]) { printf("%f\n",78.5); //00401000 fld qword ptr [__real@4053a00000000000 (408100h)] //00401006 sub esp,8 //00401009 fstp qword ptr [esp] //0040100C push offset string "%f\n" (4080FCh) //00401011 call printf (40101Ch) printf("%f\n", Mul< Mul<Double,Double> ,PI >::Value() ); //00401000 fld qword ptr [__real@4053a00000000000 (408100h)] //00401006 sub esp,8 //00401009 fstp qword ptr [esp] //0040100C push offset string "%f\n" (408108h) //00401011 call printf (401073h) return 0; }
はい。そのまんまです。
やってることは半径×半径×3.14ですね。ここでは半径は5.0です。
ちなみにコメントの部分はReleaseでコンパイルした場合のアセンブラです。
ちゃんと即値の場合と同じ処理がされてます。
簡単な内容なのに他でみたことがないのは、単に僕の勉強不足か
どっかに問題があるのか・・・