■
昼からゼミ。M1 の中間発表の準備。まだ、2週間以上あるから大丈夫? HRSW 君は音信不通、 HYS 君はバイト、 ARI さんと KTN さんは遅刻…。(あ、俺も?)
体調
昨日の夜から体調が悪い。腹が痛いし、胸がむかむかする。吐き気が…。納豆食べ過ぎたかなぁ…。
行列ライブラリ
今までのがすごく遅いので、ちょっと改良した。配列 new はデフォルトコンストラクタ Vec() でしか作れない。でも、ベクトルクラスは引数でサイズを指定したいので Vec() は禁止したい。つまり、
Vec* data_ = new Vec(n)[m];
と書きたいが、これは C++ の仕様上できないらしい。なので、
Vec* data_ = (Vec *)(new char[sizeof(Vec)*m]);
という風に、無理やり作って強制キャスト。さらに、配置 new を使って、
new(&(data_[i])) Vec(n);
(data_[i]).~Vec();
で全部破棄してから、
delete[] ((char *)data_);
…一応動いたみたい?
が、エンバグ…。9時半までかかって直した。でも、やっぱり遅いじゃん。
春の嵐
というらしい。雨と強風の一日だった。夜にはやんですっきり。
松屋
ハンバーグ部、活動再開。
テンプレートと罠
行列やベクトルのサイズをテンプレートで特殊化すればいいんじゃね?と思ったので、かいてみた。
template<size_t m, size_t n> class Mat { public: Mat(); Mat(const Mat<m, n>& M); ... private: Vec<n> data_[m]; };
という感じ。これイイ!サイズをメンバで持たなくていい!要素のメモリを動的確保しなくてイイ!サイズチェックしなくていい!使うバリエーションの数だけメモリ食うけど!どうせ 3x3 とかそれぐらいだし!!
が、ここに template が分割コンパイルできない罠が潜んでいたのでした。つまり、上のように作ったものを使うものと分離してコンパイルすると…
- 実装部分のコンパイルでは、特殊化されたものが要求されないから、作られない。例えば、
Mat<3, 3>
とか。 - 運用部分では、
Mat<3, 3>
が使いたいけど、テンプレートが宣言されてるからエラーが出ない。 - 両方をリンクしようとすると、
Mat<3, 3>
なんて無いと駄々をこねる。
これが世に言う template の罠ですね。これの解決案は 3 つ。
export
に対応したコンパイラの出現を待つ。- まるっと全部インクルード。
- 使うものは全部特殊化しておく。参考文献→http://www.fides.dti.ne.jp/~oka-t/cpplab-template-3.html
最後のはどうやるかというと、実装のソースに、
template class Mat<3, 3>; template class Mat<4, 3>;
とか、使うものをありったけ書いておく。無理!面倒!