VC6とBCCのテンプレートの扱いの違い
H鑑定してみる
突然ですが、 Googleで偶然見つけたH鑑定サイトで鑑定してみました。
結果は「俳優並み」。姿はいいが、平凡と言うことらしい。お値段は7727円。安いのか、高いのか、どう捉えればいいのだろうか。
ところで気になったのは、「運命のH相手」の覧。現在東京都で警察官をしている、22歳の女性です!だそうで、 これから東京に就職する私にとっては、ちょっとタイムリー。
ま、お遊びですから気にしない気にしない・・・。でも、気になるなぁ(^^ゞ
行列演算クラスを作ってみる
さてさて、行列演算(ベクトルも含む)というのは非常に需要が多いもので、 3Dの計算や各種の変換(フーリエ変換とか)など、 行列演算を使いたい場面が多々存在します。
で、数多くのライブラリが存在していてそれぞれ高速性とかメモリ性能とかの有用性を謳っているのですが、 やっぱりいろいろ思うところもあり、勉強もかねてまぁ私も作ってみようと思ったわけです。
それでとりあえず作りました。gmmatrix.h(まだまだ未完)。一部抜粋。
template <class T, unsigned int N, unsigned int M>
class gmatrix
{
public :
reference operator()(size_type rows, size_type cols) {
return _value[rows][cols];
}
その他いろいろ
private :
T _value[N][M];
};
T型のN×M行列を扱うクラスです。 実装はオーソドックスにTの2次元配列で、 garray(こちらを参照)と同じように使えるようにしたいということもあり、 アクセスは()演算子を使って行う形になっています。
特徴としては、
- 行・列の長さがコンパイル時に決定されること。
- STLコンテナの要件を(一部を除いて)満たしており、STLアルゴリズムが適用できること。があげられますが、それはソースを見て頂くとして、問題は次。
行列同士のかけ算をするために、
template <class T1, unsigned N, unsigned M, class T2, unsigned L>
gmatrix<T1, N, L> operator * (const gmatrix<T1, N, M>& lhs, const gmatrix<T2, M, L>& rhs)
{
gmatrix<T1, N, L> ret(0);
for (int n = 0; n < N; n++) {
for (int l = 0; l < L; l++) {
for (int m = 0; m < M; m++) {
ret(n, l) += lhs(n, m) * rhs(m, l);
}
}
}
return ret;
}
と言うテンプレート関数を作りました。
線形代数における行列の積の定義によれば、 ×記号の前の行列の列数と記号の後の行列の行数は一致する必要があって、 積の結果は記号の前の行列の行数と記号の後の行列の列数を持つ行列になります。う・・・わかりづらい。ようするに、N×M行列とM×L行列を掛けるとN×L行列ができる、 ということです。
で、それをそっくり書いたのです。一応、前後の行列の要素の型(doubleとかintとか)が違っていてもいいように、\var{T1}、\var{T2}とテンプレートにしてしまいました。わかりやすいでしょ?(テンプレート引数宣言の順序に深い意味はありません)。
そして、つぎのようなコードで使用します。
typedef moo::gmatrix<double, 4, 4> matrix44d;
typedef moo::gmatrix<double, 3, 4> matrix34d;
void foo()
{
matrix44d m44(1), n44(2); // 括弧内の数値は各要素の初期値
matrix34d m34(3);
cout << (n44 * m44) << endl; (1)
cout << (m34 * m44) << endl; (2)
cout << (m44 * m34) << endl; (3)
}
(1)は4×4行列同士のかけ算、 (2)は3×4行列と4×4行列のかけ算で結果は3×4行列、 (3)は4×4行列と3×4行列のかけ算なので、エラーです。とっても便利そうでしょ?
実はこのコードは、Visual C++ 6.0ではコンパイルできません。 どうやら行数・列数指定とテンプレート引数との対応を判断しきれないみたいです。しかし、Borland C++ 5.5ではコンパイルでき、正しく動作します。
補足:VCはテンプレート引数の特殊化に制限があるそうで、それが原因っぽいです。
Visual C++を切り捨ててしまうこともできますが、 VCは本格的な開発をする場合には無視できない重要なツールであるだけに、 そうもいきません。
C++の仕様としてはどちらが正確なのかはわかりませんが、 両方でコンパイルできるように作るのが、ライブラリを作る上では重要です。
試行錯誤は続く・・・
とりあえず、妥協点を探すべくあれこれやってみることとします。
でも、BCCにもSTL関係で挙動がおかしいものがたくさんあって、 これまた困るんだよな。
また、どちらも新しいバージョンがあるので(VC.NETとBCC5.5.1) そちらではどうなっているのかも知りたいところではあります。 特にVCはがらっと変わっているので異なる挙動も予想されます。
# 買わなきゃ調べられないのではちょっと無理だが・・・。