DOSEIの日記

技術メモ+日常ログ

昼からゼミ。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 つ。

最後のはどうやるかというと、実装のソースに、

template class Mat<3, 3>;
template class Mat<4, 3>;

とか、使うものをありったけ書いておく。無理!面倒!