tags:

views:

278

answers:

1

I am trying to write a trivial Matrix class, using C++ templates in an attempt to brush up my C++, and also to explain something to a fellow coder.

This is what I have som far:

template class<T>
class Matrix
{
public:
    Matrix(const unsigned int rows, const unsigned int cols);
    Matrix(const Matrix& m);
    Matrix& operator=(const Matrix& m);
    ~Matrix();

    unsigned int getNumRows() const;
    unsigned int getNumCols() const;

    template <class T> T getCellValue(unsigned int row, unsigned col) const;
    template <class T> void setCellValue(unsigned int row, unsigned col, T value) const;

private:
    // Note: intentionally NOT using smart pointers here ...
    T * m_values;
};


template<class T> inline T Matrix::getCellValue(unsigned int row, unsigned col) const
{
}

template<class T> inline void Matrix::setCellValue(unsigned int row, unsigned col, T value)
{
}

I'm stuck on the ctor, since I need to allocate a new[] T, it seems like it needs to be a template method - however, I'm not sure I have come accross a templated ctor before.

How can I implemnt the ctor?

+4  A: 

You can access T in the constructor, so the constructor itself needs not be a template. For example:

Matrix::Matrix(const unsigned int rows, const unsigned int cols)
{
    m_values = new T[rows * columns];
}

Consider using a smart pointer, like boost::scoped_array or std::vector for the array to make resource management a bit easier.

If your matrix has a fixed size, another option would be to take the rows and columns as template parameters along with T:

template <class T, unsigned Rows, unsigned Columns>
class Matrix 
{ 
    T m_values[Rows * Columns];
};

The biggest advantage is the size is then part of the type of a matrix, which can be useful for enforcing rules at compile-time, for example, ensuring two matrices are of compatible sizes when doing matrix multiplication. It also doesn't require the array to be dynamically allocated, which makes resource management a bit easier.

The biggest disadvantage is that you can't change the size of the matrix, so it may not work for what you need.

James McNellis
@james: thanks for the quick response. I prefer the first approach (though I can see the appeal in the other approach). One last question though (going with the first approach) - are you sure the ctor can access T (I have never seen that before). Also, is it then, a template function (the signature suggests its not). So (assuming its NOT a method template, can I then implement it in my source file (instead of the header)?
skyeagle
@skyeagle: You can use `T` anywhere inside the definition of the class template. The constructor is not a template, but as it is a member function of a class template, it must be implemented in the header. MSDN has a pretty good example of class template member functions: http://msdn.microsoft.com/en-us/library/80dx1bas(VS.100).aspx
James McNellis
Really important -- you need to use `scoped_array` if you use `new[]`.Also, I recommend using `vector` instead of an array.
rlbond
@rlbond: Good catch on the `scoped_array`. Oops!
James McNellis
@james should the ctor then be defined as Matrix<T>::Matrix() ?
skyeagle
@skyeagle: If it's defined inside the class definition, you can simply use `Matrix() { }`. If it's defined outside the class definition, you need to use `template <typename T> Matrix<T>::Matrix() { }`.
James McNellis
@james: many thanks!
skyeagle