By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,778 Members | 1,947 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,778 IT Pros & Developers. It's quick & easy.

Templating classes

P: n/a
I am working on a class that will be a matrix based on a vector of
vectors. I am having trouble with the following code causing errors on
compilation:

template<class Tclass MatrixBase
{
public:
MatrixBase()
{
width = 0;
height = 0;
matrix.clear();
}
MatrixBase(const unsigned w, const unsigned h, const T &d = T())
{
matrix.resize(w, std::vector<T>(h, d));
width = w;
height = h;
}

void AddRow(const T &d = T())
{
for (std::vector<T>::iterator i = matrix.begin(); i !=
matrix.end(); ++i)
i->push_back(d);
++height;
}
// More methods
protected:
std::vector< std::vector<T matrix;
unsigned height;
unsigned width;
};

In the AddRow method (and other, similar methods as well), it says
that it needs an ';' before i and that it's undeclared. It also says
that 'height' and 'width' are undeclared. Should I move the variable
definitions up to the top of the class or should the methods be
outside of it entirely?

Jun 1 '07 #1
Share this Question
Share on Google+
9 Replies


P: n/a
MathStuf wrote:
I am working on a class that will be a matrix based on a vector of
vectors. I am having trouble with the following code causing errors on
compilation:

template<class Tclass MatrixBase
{
public:
MatrixBase()
{
width = 0;
height = 0;
Those are better initialised.
matrix.clear();
No need to clear a freshly constructed vector.
}
MatrixBase(const unsigned w, const unsigned h, const T &d = T())
{
matrix.resize(w, std::vector<T>(h, d));
width = w;
height = h;
Again, those are better initialised than assigned.
}

void AddRow(const T &d = T())
{
for (std::vector<T>::iterator i = matrix.begin(); i !=
'matrix.begin()' returns 'std::vector<std::vector<T::iterator.
You probably want to make this loop nested.

Also, 'std::vector<T>::iterator' is a dependent name. The compiler
doesn't know that it can be used where a type is expected. You need
to tell the compiler to trust you:

for (typename std::vector<T>::iterator ...
^^^^^^^^
matrix.end(); ++i)
i->push_back(d);
If you don't make this loop nested (which is fine), you might want
to review what you're pushing.
++height;
}
// More methods
protected:
std::vector< std::vector<T matrix;
unsigned height;
unsigned width;
};

In the AddRow method (and other, similar methods as well), it says
that it needs an ';' before i and that it's undeclared.
That's because it doesn't believe that 'std::vector<T>::iterator' is
in fact a type. Use 'typename' to tell it.
It also says
that 'height' and 'width' are undeclared.
Where?
Should I move the variable
definitions up to the top of the class or should the methods be
outside of it entirely?
Not sure what you're asking here, sorry.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 1 '07 #2

P: n/a
On Jun 1, 4:39 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
MathStuf wrote:
I am working on a class that will be a matrix based on a vector of
vectors. I am having trouble with the following code causing errors on
compilation:
template<class Tclass MatrixBase
{
public:
MatrixBase()
{
width = 0;
height = 0;

Those are better initialised.
matrix.clear();

No need to clear a freshly constructed vector.
}
MatrixBase(const unsigned w, const unsigned h, const T &d = T())
{
matrix.resize(w, std::vector<T>(h, d));
width = w;
height = h;

Again, those are better initialised than assigned.
Ah, thanks.
That's because it doesn't believe that 'std::vector<T>::iterator' is
in fact a type. Use 'typename' to tell it.
It also says
that 'height' and 'width' are undeclared.

Where?
Hmm...guess I should have looked exactly where it was getting mixed up
there. It's in the following code:
template<class Tclass Matrix : public MatrixBase<T>
{
public:
Matrix()
{
width = 0;
height = 0;
matrix.clear();
}
// More methods
};

Since matrix, height, and width are protected, shouldn't they be
available to any class which inherits MatrixBase and invisible to
external interfaces? Or do I have it backwards?
Should I move the variable
definitions up to the top of the class or should the methods be
outside of it entirely?

Not sure what you're asking here, sorry.
I thought that the problem may have been matrix being defined after
the methods. It's a moot point now, since the typename fixed it.

Jun 1 '07 #3

P: n/a
MathStuf wrote:
>[redacted]

Hmm...guess I should have looked exactly where it was getting mixed up
there. It's in the following code:
template<class Tclass Matrix : public MatrixBase<T>
{
public:
Matrix()
{
width = 0;
height = 0;
matrix.clear();
}
// More methods
};

Since matrix, height, and width are protected, shouldn't they be
available to any class which inherits MatrixBase and invisible to
external interfaces? Or do I have it backwards?
I *THINK* this is one of the rare cases where you need to qualify the
member, i.e. either MatrixBase<T>::width, or this->width.
Jun 1 '07 #4

P: n/a
MathStuf wrote:
[redacted]
>
Hmm...guess I should have looked exactly where it was getting mixed up
there. It's in the following code:
template<class Tclass Matrix : public MatrixBase<T>
{
public:
Matrix()
{
width = 0;
height = 0;
matrix.clear();
}
// More methods
};

Note that since width and height are members of MatrixBase<>, it's
probably better to let MatrixBase set them. If you need something other
than what MatrixBase has set as the "default", MatrixBase should have a
constructor with width and height parameters.
Jun 1 '07 #5

P: n/a
On Jun 1, 5:11 pm, red floyd <no.s...@here.dudewrote:
MathStuf wrote:

[redacted]


Hmm...guess I should have looked exactly where it was getting mixed up
there. It's in the following code:
template<class Tclass Matrix : public MatrixBase<T>
{
public:
Matrix()
{
width = 0;
height = 0;
matrix.clear();
}
// More methods
};

Note that since width and height are members of MatrixBase<>, it's
probably better to let MatrixBase set them. If you need something other
than what MatrixBase has set as the "default", MatrixBase should have a
constructor with width and height parameters.
Alright, but I still have problems with their availability. I have
GetWidth() and GetHeight() methods in MatrixBase<>, but when i go to
call it, the compiler complains about it.

\Matrix.h:161: error: there are no arguments to `GetHeight' that
depend on a template parameter, so a declaration of `GetHeight' must
be available

I'm confused since MatrixBase<Tis inherited as public, and protected
members should be available (as well as public ones such as
GetHeight() and GetWidth()). I have other classes (non-template
though) where an id is inherited from the base class (public
inheritance of a protected variable) and straight calls to the id
works. Do templates mess with inheritance at all? I don't think they
would, but that's what it would seem is happening here.

Jun 1 '07 #6

P: n/a
MathStuf wrote:
On Jun 1, 5:11 pm, red floyd <no.s...@here.dudewrote:
>MathStuf wrote:

[redacted]


>>Hmm...guess I should have looked exactly where it was getting mixed
up there. It's in the following code:
>>template<class Tclass Matrix : public MatrixBase<T>
{
public:
Matrix()
{
width = 0;
height = 0;
matrix.clear();
}
// More methods
};

Note that since width and height are members of MatrixBase<>, it's
probably better to let MatrixBase set them. If you need something
other than what MatrixBase has set as the "default", MatrixBase
should have a constructor with width and height parameters.

Alright, but I still have problems with their availability. I have
GetWidth() and GetHeight() methods in MatrixBase<>, but when i go to
call it, the compiler complains about it.

\Matrix.h:161: error: there are no arguments to `GetHeight' that
depend on a template parameter, so a declaration of `GetHeight' must
be available
That's just not true. 'GetHeight' is non-static, so it *does* have
one argument that depends on the template argument - the instance of
the class (the object). But it doesn't really matter. The full name
of 'GetHeight' is 'MatrixBase<T>::GetHeight', which means it *does*
depend on 'T' (simply because it is a member of the template).
I'm confused since MatrixBase<Tis inherited as public, and protected
members should be available (as well as public ones such as
GetHeight() and GetWidth()). I have other classes (non-template
though)
That's *the* difference.
where an id is inherited from the base class (public
inheritance of a protected variable) and straight calls to the id
works. Do templates mess with inheritance at all?
No, but they do have slightly different rules for name lookup.
I don't think they
would, but that's what it would seem is happening here.
No, you just need to learn name lookup rules.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 1 '07 #7

P: n/a
On Jun 1, 5:46 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
MathStuf wrote:
On Jun 1, 5:11 pm, red floyd <no.s...@here.dudewrote:
MathStuf wrote:
[redacted]
>Hmm...guess I should have looked exactly where it was getting mixed
up there. It's in the following code:
>template<class Tclass Matrix : public MatrixBase<T>
{
public:
Matrix()
{
width = 0;
height = 0;
matrix.clear();
}
// More methods
};
Note that since width and height are members of MatrixBase<>, it's
probably better to let MatrixBase set them. If you need something
other than what MatrixBase has set as the "default", MatrixBase
should have a constructor with width and height parameters.
Alright, but I still have problems with their availability. I have
GetWidth() and GetHeight() methods in MatrixBase<>, but when i go to
call it, the compiler complains about it.
\Matrix.h:161: error: there are no arguments to `GetHeight' that
depend on a template parameter, so a declaration of `GetHeight' must
be available

That's just not true. 'GetHeight' is non-static, so it *does* have
one argument that depends on the template argument - the instance of
the class (the object). But it doesn't really matter. The full name
of 'GetHeight' is 'MatrixBase<T>::GetHeight', which means it *does*
depend on 'T' (simply because it is a member of the template).
Okay...I put MatrixBase<T>:: scoping on all references to height,
width, and matrix, and it seems to work fine now. Thanks for all the
help.

--MathStuf
Jun 1 '07 #8

P: n/a
>
Also, 'std::vector<T>::iterator' is a dependent name. The compiler
doesn't know that it can be used where a type is expected. You need
to tell the compiler to trust you:

for (typename std::vector<T>::iterator ...
^^^^^^^^
This is one of the reasons I like to use typedefs. It makes the code
easier to read and removes ambiguities. For example

template<class Tclass MatrixBase
{
protected:
typedef std::vector<Tmatrixrow_t;
typedef std::vector<matrixrow_tmatrix_t;

matrix_t matrix;
...

public:
void AddRow(const T &d = T())
{
for(matrix_t::iterator i = matrix.begin();
i != matrix.end(); ++i)
{
i->push_back(d);
}
++height;
}
...
};

Doing this would also make another error in the OP's code more obvious:
>template<class Tclass MatrixBase
{
public:
...
void AddRow(const T &d = T())
{
for (std::vector<T>::iterator i = matrix.begin(); i !=
matrix.end(); ++i)
i->push_back(d);
++height;
}
// More methods
protected:
std::vector< std::vector<T matrix;
unsigned height;
unsigned width;
};
matrix.begin() returns an iterator to a std::vector< std::vector<T,
not an iterator to a std::vector<T>.

Using typedefs, you'd probably notice that bug without ever even running
it through the compiler.

-- David
Jun 1 '07 #9

P: n/a
David C. wrote:
>Also, 'std::vector<T>::iterator' is a dependent name. The compiler
doesn't know that it can be used where a type is expected. You need
to tell the compiler to trust you:

for (typename std::vector<T>::iterator ...
^^^^^^^^

This is one of the reasons I like to use typedefs. It makes the code
easier to read and removes ambiguities. For example

template<class Tclass MatrixBase
{
protected:
typedef std::vector<Tmatrixrow_t;
typedef std::vector<matrixrow_tmatrix_t;

matrix_t matrix;
...

public:
void AddRow(const T &d = T())
{
for(matrix_t::iterator i = matrix.begin();
I believe you still have to use 'typename':

for (typename matrix_t::iterator i = matrix.begin();
i != matrix.end(); ++i)
{
i->push_back(d);
}
++height;
}
...
};

[..]

-- David
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 1 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.