1

行と列の両方のメジャーストレージをサポートできるMatrixテンプレートクラスを作成しています。理想的には、ストレージ形式の影響を受けるメソッドのみを専門にしたいです。ただし、(以下のように)メソッドを特殊化しようとすると、エラーメッセージしか表示されません。

enum MatrixStorage
{
    ColumnMajor,
    RowMajor
};

template< typename T,
          unsigned rows, 
          unsigned columns, 
          MatrixStorage storage = ColumnMajor >
class Matrix
{
    public:

    T & operator () ( unsigned const & row, unsigned const & column );

};

template< typename T,
          unsigned rows,
          unsigned columns >
T & Matrix< T, rows, columns, ColumnMajor >::
operator () ( unsigned const & row, unsigned const & column )
{
    return elements[ ( row + ( rows * column ) ) % ( rows * columns ) ];
}

template< typename T,
          unsigned rows,
          unsigned columns >
T & Matrix< T, rows, columns, RowMajor >::
operator () ( unsigned const & row, unsigned const & column )
{
    return elements[ ( ( row * columns ) + column ) % ( rows * columns ) ];
}

エラー出力:

error C3860: template argument list following class template name must list parameters in the order used in template parameter list
error C2976: 'maths::Matrix<T,rows,columns,storage>' : too few template arguments
error C3860: template argument list following class template name must list parameters in the order used in template parameter list

他の質問で与えられた例に従うと、構文は正しいように見えます。それでも、これを機能させる唯一の方法は、クラス自体を特殊化することです(以下のように)が、これは、ストレージ形式に依存しないすべてのメソッドを複製することを意味します。

enum MatrixStorage
{
    ColumnMajor,
    RowMajor
};

template< typename T,
          unsigned rows,
          unsigned columns,
          MatrixStorage storage = ColumnMajor >
class Matrix;

template< typename T,
          unsigned rows,
          unsigned columns >
class Matrix< T, rows, columns, ColumnMajor >
{
    T & operator () ( unsigned const & row, unsigned const & column );
};

template< typename T,
          unsigned rows,
          unsigned columns >
class Matrix< T, rows, columns, RowMajor >
{
    T & operator () ( unsigned const & row, unsigned const & column );
};
4

1 に答える 1

3

テンプレートのメンバー関数を含む関数テンプレートを部分的に特化することはできません。別の方法は、必要な機能を提供するテンプレート ヘルパー クラスを作成し、テンプレートのメンバー関数からクラス テンプレートへの呼び出しを転送することです。

または、ユースケースが非常に単純であるため、座標とモードが指定された配列のインデックスを提供するヘルパー関数 (テンプレートかどうか、完全なクラスである必要はありません) を作成できます。

template <MatrixStorage m>
int index_of( int row, int col, int rows, int columns ) {
    return ( row + ( rows * column ) ) % ( rows * columns );
}
template <>
int index_of<RowMajor>( int row, int col, int rows, int columns ) {
    return ( ( row * columns ) + column ) % ( rows * columns );
}

MatrixStorage実行時にチェックされるタイプの追加パラメーターを取ることで、非テンプレートにすることができます (simple if)

于 2012-06-08T01:33:42.893 に答える