is_sameとかあったし
こーゆーの欲しいんだけどなーと思ってて見付からなかった奴が普通にあった。
結局、こんなコードで良かった。
template <typename T> void set ( typename enable_if< is_same< uint32_t, T >, const T& >::type t ) { as_uint32 = t; }
まあ、色々練習になったから良し。
あと、unionで型変換を潰すようなのはtype erasureとか言って、boost::anyなんかでも使われてるっぽい。やっぱこれしか無いのか。だりー。Modern C++ Designとか読めば書いてあるのかなあ。まあ、ネットに転がってる情報の拾い読みと試行錯誤で何とかなるかな。だりー。
関数ポインタとデータポインタの書き分けとかは結局自前だったし。書き分ける意味多分ねーけど。
つーか、ついこないだまで「SFINAE怖いからやめとこう」とか言ってたの誰(笑)。
何故いつも寄り道を始めるのか
何か疲れたんで、今日もメタプログラミングがしたい気分になり、つらつらと見ていたらis_power_of_2が目に付いた。ああ、これコンパイルタイムに解決してみたいッスね。しようしよう。
してみた。元々assertの中でしか使ってない関数だったので、普通の関数の方が簡単便利で良かった。何てこった。
カッとなって、2の累乗で特殊化される関数とか書いて気を鎮めた。多分バイナリ全然変わらないが。
まあしかし、メタ関数の書き方や使い方にも少しだけ慣れてはきた。
関数(普通の)の引数に
typename enable_if<Cond>::type* = 0
とか書く意味もやっと理解した。要するに
typename enable_if<Cond>::type *dummy = 0
と書けば少し分かりやすいんだよな。Condが偽だとtypeが存在しないからSFINAEで実体化されない、ってのを利用する訳だけど、引数dummyを実際には書かなくていいようにしたいから初期値を書きたい訳で、ポインタ型にすればtypeがどんな型でも0は代入できるね、と。
で、dummyは使ってない引数だから名前を消すと、最初の書き方に戻る訳か、なるほど、と。
変態イディオムに支配された世界に革命は起きないんでしょうか(笑)。まあ変態イディオム好きだけどさ。新しい便利技術とかの根幹がことごとく変態に支配されてるのはやばいよなあ、言語的に。
同じ機能がすっきり書けるなら、C++はどんなに便利になることだろう。これだけ広範にクリティカルに使われてる言語だと相当動きにくいんだろうけど。
MPL辺りからかなり必死
blogにコードを貼ったりするけど、実物のコピペじゃない方が多いんですよ。その場でちゃっちゃか「こんなだったよな」と思い出しながら、ほぼ同等のコードを書くことが多い。
で、enable_ifとかmplとかのコードを貼り付けたエントリで、やたらと書き直しが多発した。つまり、まだ全然慣れてないんだろうなあ。
まーでも、STLよりはだいぶ楽な気がするんだけど。それに何つーか、他にシンプルで効率のいい手が無いから仕方ない、って使い方だから納得しやすい。std::vectorなんかはやっぱりちょっと使いたい場面が無いしなあ。バウンダリチェックとか自動伸長とか要らないし。boost::arrayは使ってみたい気もするけど。つーかvectorよりもvalarrayよりも、boost::arrayみたいなのをまず標準に入れるべきだったんじゃなかろうか。もちろんvectorも入れた方がいいけど。あとvector<bool>は略。
まあ、iostreamとかもなあ…。しかも標準入出力だから、大抵最初の方で紹介されるんだよな。cout << "hello work" << endl;
とか書いて「これがC++っぽい書き方です」的に。そりゃ標準出力だから早めに紹介するよな。
演算子オーバーロードの曲芸は良くないよなあ(笑)。と言いつつもboost::formatとか超便利に使ってますが。