普通にenable_if使えたし


 普通に考えて使えそうだったしー。馬鹿じゃーん。
 つーか、ちゃんとBoostの例文通りに書いたら通った。英文だから面倒で見てなかった。

 いや、何でこんなん使いたかったかっつーと、スレッド間で受け渡すのは結局全部PODになってて、送受信の時に無理矢理型変換とかしてる訳ですよ。えらい低レベルになったような。shared_ptr何それ的な。
 で、unsignedもsignedもfloatもdoubleもポインタもビット列変換無しに出し入れする関数が欲しくなった。
 enable_if無しで失敗した時は、まあ明示的に型指定なり関数名で型を明示するなりして我慢しようと思ったのだが、異常に大量の型明示が発生した。その上、typedefで隠蔽されたAPI引数型とかを相手にしなきゃならなくなってきて、実際の型を確認して適合する関数を毎回指定するとかやってたら色々と本末転倒かつかなり問題があるんで、どうしてもオーバーロードなりテンプレートなりで解決したくなった訳だ。boost::anyはvptrとかRTTIとか噛んでそうなので無しで。

 具体的には(実物とはだいぶ違うけど)、まずこんな感じに書いて失敗した。何度目だ。

void set ( int t ) { set_int(t); }
void set ( unsigned int t ) { set_uint(t); }
void set ( float t ); // 以下実装略
void set ( void* t );

 これでfoo.set(uint32_data);とか呼ぶと「引数tはunsigned intなんだけど、型変換すれば使える関数が三つもあるよ! どれ使えばいいの!」とかいつものクソバカなエラー吐くんで、

template <typename T>
void set ( typename enable_if< is_signed<T>, T >::type t ) {
  set_int(t);
}
template <typename T>
void set ( typename enable_if< is_unsigned<T>, T >::type t ) {
  set_uint(t);
}
// 以下略

こんなん書いたらコンパイル通った。読み出しもインライン最適化に期待してT&を受け取る気持ち悪いテンプレート関数にした。これで型の明示も関数名書き換えも無しに読み書き可能になった。万歳。asm見たらインラインになってなかったけど。いきなりjmpするPROCとかひどいのが出来てた(笑)。まあリンクタイムの最適化もあるしな。というよりそこまでシビアじゃないっつーに。

 つーか、もっといい手は無いんだろうか。
 C的に考えると、マクロか何かで(*((uint_32t*)&t))こんなんに変換するとか。シンプルではあるなあ。オーバーロードも何も要らんですな。最適化も掛かりやすそうな。まあ今更か。不便で危険だけどシンプルで僅かに効率的かもしれない、ってことだしなあ。
 あー、64-bit対応の時はuint64_t版にifdefとかで書き換えが発生したりするのか。まー大した手間でもない気はするが。
 そういえばreinterpret_castもやったけど、static_castが出来る時はそっちでやれ、とコンパイラに怒られた。うぜえ(笑)。

(Visited 3 times, 1 visits today)

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください