I am currently in the process of implementing a scientific toolkit using C++. When i implemented the Matrix class i encountered a problem with the conversion constructor:
template<size_t ROWS, size_t COLS = ROWS>
class Matrix {
public:
...
/** \brief Creates a matrix from a vector */
Matrix<ROWS, 1> (const Vector<ROWS>& vector) {
for (size_t i = 0; i < ROWS; i++) {
(*this)[i][0] = vector[i];
}
...
}
This code compiles just fine with clang++, but fails using g++ with
matrix.h:43:18: error: invalid declarator before ‘(’ token
Matrix<ROWS, 1> (const Vector<ROWS>& vector) {
Is there any other way to force certain template arguments for specific constructors? Is the way i am doing it not standard-compliant or should i report a bug to gcc?
Use partial specialization like this:
template<size_t ROWS, size_t COLS = ROWS>
class Matrix {
// ... (regular ROWS x COLS matrix code)
};
template<size_t ROWS>
class Matrix<ROWS, 1u> {
// ... (more ROWS x 1 matrix code)
/// \brief Creates a matrix from a vector
Matrix(const Vector<ROWS> & vector) {
for (size_t i = 0u; i < ROWS; i++)
(*this)[i][0u] = vector[i];
}
// ... (more ROWS x 1 matrix code)
};
Or if this would result in too much code duplication, just declare a common base class for the specializations. For example something like this (in c++11):
template<size_t ROWS, size_t COLS = ROWS>
class MatrixBase {
// ... (regular ROWS x COLS matrix code)
};
template<size_t ROWS, size_t COLS = ROWS>
class Matrix: public MatrixBase<ROWS, COLS> {
public: /* Methods: */
using MatrixBase<ROWS, COLS>::MatrixBase;
};
template<size_t ROWS>
class Matrix<ROWS, 1u>: public MatrixBase<ROWS, 1u> {
public: /* Methods: */
using MatrixBase<ROWS, 1u>::MatrixBase;
Matrix(const Vector<ROWS> & vector) {
for (size_t i = 0u; i < ROWS; i++)
(*this)[i][0u] = vector[i];
}
};
For C++03 and earlier you can't use the using keyword this way and may still have to define constructors for all specializations which call the respective base class constructors, e.g. Matrix(SomeArg arg) : MatrixBase(arg) {}. And if you're using GCC 4.7 where this C++11 using statement is not supported, you can use perfect forwarding to avoid writing separate constructors in the specializations for all base class constructors, e.g. template <typename ... Args> Matrix(Args && ... args) : MatrixBase(std::forward<Args>(args)...) {}.
Is it necessary to reimplement all methods, or is it somehow possible to use unspecialized methods in the specialized template without duplicating code?
A partially-specialized class doesn't contain declarations of the primary template's member functions, static member functions, enumerations, member classes, etc. Therefore you would have to redefine the entire class and reimplement them if you want to use them. As an alternative, if you have C++11 support, you can use constructor delegation by calling a private constructor based on a given condition:
template<size_t ROWS, size_t COLS = ROWS>
class Matrix
{
public:
Matrix(const Vector<ROWS>& vector)
: Matrix(vector, std::integral_constant<bool, COLS == 1>())
{ }
private:
// Implementation for COLS == 1
Matrix(const Vector<ROWS>& vector, std::true_type)
{
}
// Implementation for COLS != 1
Matrix(const Vector<ROWS>& vector, std::false_type)
{
}
};
Related
I am implementing a Matrix class in C++ and I want to be able to initialize it with an intializer list like so:
Matrix<double, 2, 3> m({{1,2,1},
{0,1,1}});
In the class I have implemented the constructor like this:
template<typename Ty, unsigned int rows, unsigned int cols>
class Matrix
{
std::array<std::array<Ty, cols>, rows> data;
public:
Matrix(const std::initializer_list<std::initializer_list<Ty>>& list)
{
int i = 0;
for (auto& list_row : list)
{
int j = 0;
for (auto& list_value : list_row)
{
data[i][j++] = list_value;
}
i++;
}
}
}
The code work but I have a couple of questions. Is it possible to make it safe, so it only takes initializer lists of a certain size(the size of the matrix) and secondly can I make the code more concise - I had imagined something like this:
Matrix(const std::initializer_list<std::initializer_list<Ty>>& list)
: data(list)
{ }
And it doesn't work but any better way to do it would be appreciated.
There's a pretty easy way to make it safe:
template<typename Ty, unsigned int rows, unsigned int cols>
class Matrix
{
std::array<std::array<Ty, cols>, rows> data;
public:
Matrix(std::array<std::array<Ty, cols>, rows> const& in)
: data(in)
{ }
};
This lets you almost use the syntax you want - you just need one extra set of {}s.
There's no way to statically enforce the size of a std::initializer_list - you'd have to assert or throw to prevent me from passing in a bunch of extra values and causing you to perform out-of-range writes.
If I call the default constructor inside the other constructor it crashes my program.I believe that array_ isn't dynamically allocated inside the default constructor.How do I fix this.
template < typename T >
class Matrix
{
public :
size_t n_{1};
size_t m_{1};
T* array_{nullptr};
public :
Matrix();
Matrix(size_t n, size_t m) {
n_ = n;
m_ = m;
array_ = new T[n_ * m_];
Matrix();
}
}
template < typename T >
Matrix<T>::Matrix(){
for(int i=0;i < n_ * m_; i++)
array_[i] = {};
}
I would structure the code like this:
template <typename T>
class Matrix
{
size_t n_;
size_t m_;
T* array_;
public:
Matrix() : Matrix(1, 1) {}
Matrix(size_t n, size_t m) : n_(n), m_(m), array_(new T[n_ * m_]()) {}
~Matrix() { delete [] array_; }
// ...
};
This achieves the same effect as your code intended (i.e. the default constructor produces a 1 × 1 matrix, and all elements are value-initialized), but it uses core language features to express this succinctly:
Initializer lists initialize class members, no assignment needed.
The array-new expression can take an initializer () to value-initialize each element; no loop is needed.
The default constructor delegates to the general constructor.
Be very careful to follow the Rule of Five if you plan to make your matrix class copyable. If all you need is an uncopyable (but movable) type, then change the type of array_ to std::unique_ptr<T[]> and remove the custom destructor.
Instead of the presented not-working code,
template < typename T >
class Matrix
{
public :
size_t n_{1};
size_t m_{1};
T* array_{nullptr};
public :
Matrix();
Matrix(size_t n, size_t m) {
n_ = n;
m_ = m;
array_ = new T[n_ * m_];
Matrix();
}
}
template < typename T >
Matrix<T>::Matrix(){
for(int i=0;i < n_ * m_; i++)
array_[i] = {};
}
just use a std::vector for the storage:
template < typename T >
class Matrix
{
private:
Size n_ = 1;
Size m_ = 1;
std::vector<T> array_;
public :
Matrix(): array_(1) {}
Matrix( const Size n, const Size m )
: n_( n ), m_( m ), array_( n*m )
{}
};
This takes care of the default-initialization of the matrix elements.
It also takes care of copying, which would cause Undefined Behavior with the original code.
In other news, where you want a default-initialized raw array, or more precisely a “value-initialized” raw array, you do
new T[size]()
where the () asks for initialization.
This is much cleaner than using a loop: it avoids that code, and it avoids doing the work twice for a class item type with default constructor.
But don't do that now: just use a std::vector for the storage, as explained above.
You don't really need a default constructor, as much as you need default constructor parameters.
Delegating c'tors, as added to c++11 were meant to add the option of "doing some base work and then some". In your case, there is no base work, only default size parameters.
The code you presented is incomplete, but if you don't plan on going with std::vector, don't forget to follow the rule of three (now five with c++11).
template < typename T >
class Matrix
{
private:
int n_;
int m_;
T* array_{nullptr};
public :
Matrix(int n = 1, int m = 1 ) : n_{n}, m_{m} {
array_ = new T[m * n];
for(int i=0;i < n_ * m_; i++)
array_[i] = 0; // If you want specific values
// otherwise no need for the loop.
}
}
};
As you've done it you shouldn't, as the default constructor will only allocate a 1 by 1 array.
What you can do, however, is delegate from the default constructor to the one that accepts two values.
Matrix() : Matrix(1,1) {};
Matrix(size_t m, size_t n) : array(new T [n*m]), n_(n), m_(m)
{
for(int i=0;i < n_ * m_; i++)
array_[i] = {};
};
A statement Matrix() in the body of a function (including a constructor) constructs a separate temporary object. It is not constructor delegation.
I need help in something really simple, which C++ makes very difficult. I created a class, lattice, with the aim to initialize and treat a matrix. There are the following private members:
private unsigned dim;
private double matrix [dim][dim];
I would like to initialize the variable dim in the constructor of the class through a parameter, but the compiler continue to return errors. I tried to make dim public and static and initializing it in the main program, but there are still problems. How could I create this simple class?
Moreover, I also implemented some methods in the class in order to update the values of the matrix. Is it true that, initializing an object of the class in a main program and then using its "updating" methods, the values of the matrix are stored only once?
Thank you for your help.
There are (at least) three ways to create such a class:
with a template
template<size_t dim>
class Matrix
{
private:
double matrix[dim][dim];
}
with the use of built in types such as std::vector (e.g. valarray would work too)
#include <vector>
class Matrix
{
private:
size_t dim;
std::vector<std::vector<double> > matrix;
public:
Matrix(size_t dim_) : dim(dim_), matrix()
{
matrix.resize(dim);
for ( size_t i = 0; i < dim; ++i )
matrix[i].resize(dim);
}
}
with the use of plain arrays (I do not recommend that!)
class Matrix
{
private:
size_t dim;
double** matrix;
public:
Matrix(size_t dim_) : dim(dim_), matrix()
{
matrix = new double*[dim];
for ( size_t i = 0; i < dim; ++i )
matrix[i] = new double[dim];
}
~Matrix() // you need a destructor!
{
for ( size_t i = 0; i < dim; ++i )
delete [] matrix[i];
delete [] matrix;
}
}
Use template:
template<int dim>
class Lattice{
double matrix[dim][dim];
}
and initialize dim in the constructor:
Lattice<10> sampleLattice;
Then dim = 10;
You might use pointer, or vector of a vector, but template is what I would use because it is less confusing and convenient.
BTW you will have to use private: and public: (with colon).
I'm guessing your "problems" are the compiler complaining about array initialization with non const size.
You should do something like this:
class MyClass {
public:
MyClass(unsigned pdim);
private:
MyClass();
const unsigned dim;
const double matrix [dim][dim];
};
MyClass::MyClass(unsigned pdim) : dim(pdim) {
// Other things
}
You can have const members inside a class but they need to be initialized using the : syntax.
I'm teaching myself c++ by creating my own data structure class (a matrix, to be exact) and I've changed it to a template class of type <T> from only using doubles. The overloaded matrix operators were pretty standard
// A snippet of code from when this matrix wasn't a template class
// Assignment
Matrix& operator=( const Matrix& other );
// Compound assignment
Matrix& operator+=( const Matrix& other ); // matrix addition
Matrix& operator-=( const Matrix& other ); // matrix subtracton
Matrix& operator&=( const Matrix& other ); // elem by elem product
Matrix& operator*=( const Matrix& other ); // matrix product
// Binary, defined in terms of compound
Matrix& operator+( const Matrix& other ) const; // matrix addition
Matrix& operator-( const Matrix& other ) const; // matrix subtracton
Matrix& operator&( const Matrix& other ) const; // elem by elem product
Matrix& operator*( const Matrix& other ) const; // matrix product
// examples of += and +, others similar
Matrix& Matrix::operator+=( const Matrix& rhs )
{
for( unsigned int i = 0; i < getCols()*getRows(); i++ )
{
this->elements.at(i) += rhs.elements.at(i);
}
return *this;
}
Matrix& Matrix::operator+( const Matrix& rhs ) const
{
return Matrix(*this) += rhs;
}
But now that Matrix can have a type, I'm having trouble determining which of the matrix references should be type <T> and what the consequences would be. Should I allow dissimilar types operate on each other (eg., Matrix<foo> a + Matrix<bar> b is valid)? I'm also a little fuzzy on how
One reason I'm interested in dissimilar types is to facilitate the use of complex numbers in the future. I'm a newbie at c++ but am happy to dive in over my head to learn. If you're familiar with any free online resources that deal with this problem I would find that most helpful.
Edit: no wonder no one thought this made sense all of my angle brackets in the body were treated as tags! I can't figure out how to escape them, so I'll inline code them.
I figure that I should illustrate my comment about parameterizing matrix dimensions, since you might not have seen this technique before.
template<class T, size_t NRows, size_t NCols>
class Matrix
{public:
Matrix() {} // `data` gets its default constructor, which for simple types
// like `float` means uninitialized, just like C.
Matrix(const T& initialValue)
{ // extra braces omitted for brevity.
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = initialValue;
}
template<class U>
Matrix(const Matrix<U, NRows, NCols>& original)
{
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = T(original.data[i][j]);
}
private:
T data[NRows][NCols];
public:
// Matrix copy -- ONLY valid if dimensions match, else compile error.
template<class U>
const Matrix<T, NRows, NCols>& (const Matrix<U, NRows, NCols>& original)
{
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = T(original.data[i][j]);
return *this;
}
// Feel the magic: Matrix multiply only compiles if all dimensions
// are correct.
template<class U, size_t NOutCols>
Matrix<T, NRows, NOutCols> Matrix::operator*(
const Matrix<T, NCols, NOutCols>& rhs ) const
{
Matrix<T, NRows, NOutCols> result;
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NOutCols; ++j)
{
T x = data[i][0] * T(original.data[0][j]);
for(size_t k = 1; k < NCols; ++k)
x += data[i][k] * T(original.data[k][j]);
result[i][j] = x;
}
return result;
}
};
So you'd declare a 2x4 matrix of floats, initialized to 1.0, as:
Matrix<float, 2, 4> testArray(1.0);
Note that there is no requirement for the storage to be on the heap (i.e. using operator new) since the size is fixed. You could allocate this on the stack.
You can create another couple matrices of ints:
Matrix<int, 2, 4> testArrayIntA(2);
Matrix<int, 4, 2> testArrayIntB(100);
For copying, dimensions must match though types do not:
Matrix<float, 2, 4> testArray2(testArrayIntA); // works
Matrix<float, 2, 4> testArray3(testArrayIntB); // compile error
// No implementation for mismatched dimensions.
testArray = testArrayIntA; // works
testArray = testArrayIntB; // compile error, same reason
Multiplication must have the right dimensions:
Matrix<float, 2, 2> testArrayMult(testArray * testArrayIntB); // works
Matrix<float, 4, 4> testArrayMult2(testArray * testArrayIntB); // compile error
Matrix<float, 4, 4> testArrayMult2(testArrayIntB * testArray); // works
Note that, if there's a botch, it is caught at compile time. This is only possible if the matrix dimensions are fixed at compile time, though. Also note that this bounds checking results in no additional runtime code. It's the same code that you'd get if you just made the dimensions constant.
Resizing
If you don't know your matrix dimensions at compile time, but must wait until runtime, this code may not be of much use. You'll have to write a class that internally stores the dimensions and a pointer to the actual data, and it will need to do everything at runtime. Hint: write your operator [] to treat the matrix as a reshaped 1xN or Nx1 vector, and use operator () to perform multiple-index accesses. This is because operator [] can only take one parameter, but operator () has no such limit. It's easy to shoot yourself in the foot (force the optimizer to give up, at least) by trying to support a M[x][y] syntax.
That said, if there's some kind of standard matrix resizing that you do to resize one Matrix into another, given that all dimensions are known at compile time, then you could write a function to do the resize. For example, this template function will reshape any Matrix into a column vector:
template<class T, size_t NRows, size_t NCols>
Matrix<T, NRows * NCols, 1> column_vector(const Matrix<T, NRows, NCols>& original)
{ Matrix<T, NRows * NCols, 1> result;
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
result.data[i * NCols + j][0] = original.data[i][j];
// Or use the following if you want to be sure things are really optimized.
/*for(size_t i = 0; i < NRows * NCols; ++i)
static_cast<T*>(result.data)[i] = static_cast<T*>(original.data)[i];
*/
// (It could be reinterpret_cast instead of static_cast. I haven't tested
// this. Note that the optimizer may be smart enough to generate the same
// code for both versions. Test yours to be sure; if they generate the
// same code, prefer the more legible earlier version.)
return result;
}
... well, I think that's a column vector, anyway. Hope it's obvious how to fix it if not. Anyway, the optimizer will see that you're returning result and remove the extra copy operations, basically constructing the result right where the caller wants to see it.
Compile-Time Dimension Sanity Check
Say we want the compiler to stop if a dimension is 0 (normally resulting in an empty Matrix). There's a trick I've heard called "Compile-Time Assertion" which uses template specialization and is declared as:
template<bool Test> struct compiler_assert;
template<> struct compiler_assert<true> {};
What this does is let you write code such as:
private:
static const compiler_assert<(NRows > 0)> test_row_count;
static const compiler_assert<(NCols > 0)> test_col_count;
The basic idea is that, if the condition is true, the template turns into an empty struct that nobody uses and gets silently discarded. But if it's false, the compiler can't find a definition for struct compiler_assert<false> (just a declaration, which isn't enough) and errors out.
Better is Andrei Alexandrescu's version (from his book), which lets you use the declared name of the assertion object as an impromptu error message:
template<bool> struct CompileTimeChecker
{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {}; \
(void)sizeof(CompileTimeChecker<(expr)>(ERROR_##msg())); }
What you fill in for msg has to be a valid identifier (letters, numbers, and underscores only), but that's no big deal. Then we just replace the default constructor with:
Matrix()
{ // `data` gets its default constructor, which for simple types
// like `float` means uninitialized, just like C.
STATIC_CHECK(NRows > 0, NRows_Is_Zero);
STATIC_CHECK(NCols > 0, NCols_Is_Zero);
}
And voila, the compiler stops if we mistakenly set one of the dimensions to 0. For how it works, see page 25 of Andrei's book. Note that in the true case, the generated code gets discarded so long as the test has no side effects, so there's no bloat.
I'm not sure I understand what you're asking.
But I would point out that your operator declarations are incorrect and/or incomplete.
Firstly, the assignment operator should return the same type as its parameter; viz:
const Matrix& operator=(const Matrix& src);
Secondly, binary operators return a new object, so you can't return a reference. All binary operators should be declared thus:
Matrix operator+( const Matrix& other ) const; // matrix addition
Matrix operator-( const Matrix& other ) const; // matrix subtracton
Matrix operator&( const Matrix& other ) const; // elem by elem product
Matrix operator*( const Matrix& other ) const; // matrix product
Actually, it is considered better style to declare and implement binary operators as global friend functions instead:
class Matrix { ... };
inline Matrix operator+(const Matrix& lhs,const Matrix& rhs)
{ return Matrix(lhs)+=rhs; }
Hope this helps.
Now I understand what you're asking.
Presumably your implementation of various operators will in this case consist of operations on the composite types. So really the question of whether Matrix op Matrix is meaningful depends on whether string op int is meaningful (and whether such a thing might be useful). You would also need to determine what the return type might be.
Assuming the return type is the same as the LHS operand, the declarations would look something like:
template <typename T>
class Matrix
{
template <typename U>
Matrix<T>& operator+=(const Matrix<U>& rhs);
};
template <typename T,typename U>
Matrix<T> operator+(const Matrix<T>& lhs,const Matrix<U>& rhs)
{ return Matrix<T>(lhs)+=rhs; }
Matrix<double> x = ...;
Matrix<int> y = ...;
cout << x + y << endl; // prints a Matrix<double>?
OK, that's doable, but the problem gets tricky quickly.
Matrix<double> x = ...
Matrix<complex<float>> y = ...
cout << x + y << endl; // Matrix<complex<double>>?
You will most likely be happiest if you require that your binary operators use like-type operands and force your application builders to explicitly type-cast their values. For the latter case:
cout << ((Matrix<complex<double>>) x) + ((Matrix<complex<double>>) y) << endl;
You can provide a member template constructor (or a type conversion operator) to support the conversions.
template <typename T>
class Matrix {
...
public:
template <typename U>
Matrix(const Matrix<U>& that) {
// initialize this by performing U->T conversions for each element in that
}
...
};
The alternative, having your binary operator template deduce the correct Matrix return type based on the element types of the two operands, requires some moderately complex template meta-programming, probably not what you're looking to get into.
First of all, the copy assignment operator should not have const Matrix& as its return type; your interface is correct.
Grant's suggestion of how binary operators are implemented is the generally accepted way of doing these things.
It's a nice exercise, but one quickly sees why doing linear algebra in C++ is a bad idea to begin with. Operations like A+B and A*B are valid only if the dimensions of the matrices match up.
You don't have to add much at all, because inside a template, the class name itself refers to the current template parameter. So the following are equivalent:
template <typename T> struct Foo
{
Foo<T> bar(const Foo<T> &);
Foo bar2(const Foo *); // same
};
So all your operations just go through without change. What you should add is a constructor that converts one matrix type into another:
temlate <typename T> class Matrix
{
template <typename U> Matrix(const Matrix<U> &); // construct from another matrix
/*...*/
};
Using that conversion constructor, you can mix matrices in your operators, as Matrix<T>::operator+(Matrix<U>) will use the conversion to create an argument of type Matrix<T>, and then you use your already implemented operator.
In C++11 you can add static_assert(std::is_convertible<U, T>::value, "Boo"); to your converting constructor to give you a useful compile-time diagnostic if you call it with an incompatible type.
Edit:
Note that my final purpose here is not having the class working, is just learning more about templates :-)
Suppose you have a template class which implements a vector:
template <typename T>
class Vector
{
public:
Vector(size_t dim) {
dimension = dim;
elements = new T[dim];
}
/* Here more stuff, like operator[] etc... */
private:
size_t dimension;
T * elements;
}
And suppose you want to build a matrix with it. A matrix is just a vector of vectors, thus it can be designed as follows:
template <typename T>
class Matrix : public Vector<Vector<T> >
{
/*...*/
}
And here comes trouble: In the constructor I need to provide rows and columns as parameter to the internal vectors. It should be something like
template <typename T>
Matrix<T>::Matrix (size_t ncols, size_t nrows)
: Vector<Vector<T> > /* Here I need to specify size for both
* internal and external vectors */
{
}
Obviously I cannot write Vector<Vector<T>(nrows)>(ncols), but that's what I would need!
A possible solution would be including size inside the template:
template <typename T, size_t N>
class Vector
{
public:
Vector() {
elements = new T[N];
}
/* Here more stuff, like operator[] etc... */
private:
T * elements;
}
Hence I would no longer need constructor parameters, but this also forces me to write clumsy code with templates everywhere (by exmample, every function using a Vector should be declared as
template <typename T, size_t N>
void foo (Vector<T,N> &vec) {...}
Do you have better solutions?
EDIT:
As solution I took inspiration from Mr Fooz's and chubsdad's posts. That's how I fixed the problem:
/* The RowAccess class is just an array wrapper which raises an exception
* if you go out of bounds */
template <typename T>
class RowAccess
{
public:
RowAccess (T * values, unsigned cols) : values(vals), cols(c) {}
T & operator[] (unsigned i) throw (MatrixError) {
if (i < cols) return values[i];
else throw MatrixError("Column out of bound");
}
private:
T * values;
unsigned cols;
};
template <typename T>
class Matrix
{
public:
Matrix (unsigned rows, unsigned cols) {...}
virtual ~Matrix () {...}
RowAccess<T> operator[] (unsigned row) {
if (row < rows) return RowAccess<T>(values + cols * row, cols);
else throw MatrixError("Row out of boundary");
}
private:
unsigned rows;
unsigned cols;
T * values;
};
Thanks a lot to everyone!
In OO terms, I would vote for "has" a relationship between Matrix and a Vector. A Matrix has vectors, rather than a Matrix "is a" vector, which means that Matrix should not derive from Vector.
EDIT 1: A small correction. "..which means that Matrix should not derive "publicly" from Vector". Private inheritance may be still fine.
Use placement-new like this (burried behind the uninitialized_fill call)
template <typename T>
class Vector
{
public:
Vector(size_t dim, T const& c = T()) {
dimension = dim;
elements =
static_cast<T*>(operator new(sizeof(T) * dim));
std::uninitialized_fill(elements, elements + dim, c);
}
/* Here more stuff, like operator[] etc... */
private:
size_t dimension;
T * elements;
};
Then you can call the constructor with Matrix::Vector(ncols, Vector<T>(nrows)) (you don't need to repeat the argument for the outer Vector, because Vector refers to Vector< Vector<T> > automatically since you inherit from the outer Vector. You need to make sure to call destructors manually before doing operator delete(elements) in the destructor then.
You might also want to embed the vector as a member, which i would probably prefer because I imagine not necessarily all operations of the outer vector make sense for a matrix. Then the initialization looks like m(ncols, Vector<T>(nrows)).
It should be noted that std::vector can also be used for this
template <typename T>
class Vector
{
public:
Vector(size_t dim, T const& c = T()):elements(dim, c)
{ }
private:
std::vector<T> elements;
};
This is an easy and safe way to accomplish that, and you get automatic memory management.
This isn't what you asked, but there's a good chance the matrix would be better of implemented as a single linear vector where you provide high-level access methods that do the indexing (e.g. elmLoc=row*ncols+col). This way you don't need to create and initialize a vector of vectors. You also don't need to worry about accidentally having some inner vectors of the differing size. All dense matrix implementations I have ever used use a single linear vector as the underlying implementation.
It depends on what you expect from your Vector (and Matrix) class.
Either you want the size to be determined at runtime, and in that case, I'd suggest adding a resize() function which would allow you to size the Vector in the constructor as you like.
template <typename T>
class Vector
{
public:
Vector(size_t dim) {
dimension = dim;
elements = new T[dim];
}
Vector() : dimension(0), elements(0) {} // you need default constructor
void resize(size_t dim) { // note: this could be implemented a lot better
T* new_elements=new T[dim];
for(int i=0; i<dim && i<dimension; i++)
new_elements[i]=elements[i];
delete [] elements;
elements=new_elements; dimension=dim;
}
/* Here more stuff, like operator[] etc... */
private:
size_t dimension;
T * elements;
}
You would then resize your Vectors in the Matrix constructor in a loop.
If you want the size of your vector or matrix to be determined at compile time, the best thing probably would be to use the template non-type argument as you suggested.