I’m writing a Matrix template class that can support both row and column major storage. Ideally I’d like to specialise only the methods that are affected by the storage format. However, when I try to specialise a method (as below) I get nothing but error messages.
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 output:
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
Following the examples given in other questions it looks like the syntax is correct. Still, the only way I can get this to work is by specialising the class itself (as below), but this means duplicating all of the methods that aren’t dependent on the storage format.
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 );
};
You cannot partially specialize function templates, which include member functions of a template. The alternative would be creating a template helper class that provides the functionality you need, and then forward the call to the class template from the member functions of your template.
Alternatively, as your use case is quite simple, you can write a helper function (template or not, no need for it to be a full class) that will provide you with the index in the array given the coordinates and the mode.
You can make it non template by taking an extra parameter of type
MatrixStoragethat will be checked at runtime (simpleif)