私は行列クラスを書いています。この定義を見てください:
template <typename T, unsigned int dimension_x, unsigned int dimension_y>
class generic_matrix
{
...
generic_matrix<T, dimension_x - 1, dimension_y - 1>
minor(unsigned int x, unsigned int y) const
{ ... }
...
}
template <typename T, unsigned int dimension>
class generic_square_matrix : public generic_matrix<T, dimension, dimension>
{
...
generic_square_matrix(const generic_matrix<T, dimension, dimension>& other)
{ ... }
...
void foo();
}
generic_square_matrix クラスは、行列の乗算などの追加機能を提供します。これを行うことは問題ありません:
generic_square_matrix<T, 4> m = generic_matrix<T, 4, 4>();
コンストラクターにより、タイプが generic_square_matrix でなくても、任意の正方行列を M に割り当てることができます。これが可能なのは、サポートされている関数のみで、データが子全体で変更されないためです。これも可能です:
generic_square_matrix<T, 4> m = generic_square_matrix<T, 5>().minor(1,1);
ここでも同じ変換が適用されます。しかし、ここで問題が発生します。
generic_square_matrix<T, 4>().minor(1,1).foo(); //problem, foo is not in generic_matrix<T, 3, 3>
これを解決するには、generic_square_matrix::minor が generic_matrix の代わりに generic_square_matrix を返すようにします。これを行う唯一の方法は、テンプレートの特殊化を使用することだと思います。しかし、特殊化は基本的に別のクラスのように扱われるため、すべての関数を再定義する必要があります。派生クラスの場合とは異なり、特殊化されていないクラスの関数を呼び出すことはできないため、関数全体をコピーする必要があります。これはあまり優れたジェネリック プログラミング ソリューションではなく、多くの作業が必要です。
C ++には、私の問題に対する解決策がほとんどあります。派生クラスの仮想関数は、基本クラスが返すクラスから派生したクラスである場合、基本クラスが返すものとは異なるクラスへのポインターまたは参照を返すことができます。generic_square_matrixはgeneric_matrixから派生していますが、関数はポインターも参照も返さないため、ここでは当てはまりません。
この問題の解決策はありますか (まったく別の構造が関係している可能性があります。私の唯一の要件は、次元がテンプレート パラメーターであり、正方行列に追加機能を持たせることができることです)。
前もって感謝します、
ルード