-
January 14th, 2009, 11:34 AM
#1
const Class& class
friend ostream& operator<<(ostream& output, const Matrix& matrix)
Error 2 error C2662: 'Matrix<T>::YDim' : cannot convert 'this' pointer from 'const Matrix<T>' to 'Matrix<T> &'
I seem to get the same error for all of the functions I'm defining with a const Matrix& matrix, but when I remove the const it works fine.
Thanks in advance!
-
January 14th, 2009, 11:47 AM
#2
Re: const Class& class
Well what is the Matrix class? Post the class declaration? Is this a template class? Someone might recognize the error and have an epiphany but it is always better to post enough code so that other people can drag and drop the text into a file and compile it themselves.
-
January 14th, 2009, 11:48 AM
#3
Re: const Class& class
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
January 14th, 2009, 12:01 PM
#4
Re: const Class& class
Most likely cause is YDim needs to be declared const:
Matrix<T>::YDim() const
{
}
-
January 14th, 2009, 12:06 PM
#5
Re: const Class& class
Sorry about that....
template <typename T>
class Matrix
{
private:
T** mMatrix;
T mValue;
public:
Matrix(size_t pRows, size_t pCols, const T& value)
{
size_t i, j; // General purpose loop variables
mValue = value;
mMatrix = new T* [pRows+1]; ; // Allocate rows
for(i=0; i<pRows; i++)
mMatrix[i] = new T[pCols+1]; // Allocate columns
mMatrix[i] = new T[1]; // Allocate sentinel row
// initialize mMatrix
for(i=0; i<pRows; i++)
{
size_t j;
for(j=0; j<pCols; j++)
mMatrix[i][j] = value; // initialize column with value
mMatrix[i][j] = (T) -1; // Add sentinel to end of column
}
mMatrix[i][0] = (T) -1; // Add sentinel to last row
}
~Matrix() { Destroy(); }
void Destroy()
{
for(size_t y=0; y<YDim(); y++)
{
delete mMatrix[y];
mMatrix[y]=0;
}
delete mMatrix;
mMatrix=0;
}
size_t& YDim()
{
size_t i=-1; // General purpose loop variables
if(mMatrix!=0)
for(i=0; mMatrix[i]!=0;i++)
if(mMatrix[i][0]== (T) -1) break;
return i;
}
size_t& XDim()
{
size_t j=-1; // General purpose loop variables
if(YDim()>0)
for(j=0; mMatrix[0][j] != (T) -1; j++);
return j;
}
T operator()(size_t row, size_t col)
{
return mMatrix[row][col];
}
bool ResetRow(size_t row)
{
return ResetRowTo(row, mValue);
}
bool ResetRowTo(size_t row, T value)
{
if(YDim()!=-1 && row<YDim())
{
for(size_t j=0; mMatrix[row][j] != (T) -1; j++)
mMatrix[row][j] = value;
return 1;
}
else
return 0;
}
friend ostream& operator<<(ostream& output, Matrix& matrix)
{
for(size_t y=0; y<matrix.YDim(); y++)
{
for(size_t x=0; x<matrix.XDim(); x++)
{
cout << matrix(y,x) << " ";
}
cout << endl;
}
return output;
}
};
-
January 14th, 2009, 12:24 PM
#6
Re: const Class& class
If the function accepts 'matrix' as a const reference then it is not allowed to modify it. XDim & YDim members are not 'const' and therefore are not allowed to be called here, as they do not promise not to change the class.
"It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
Richard P. Feynman
-
January 14th, 2009, 12:27 PM
#7
Re: const Class& class
please use [code][/code] tags when posting code.
You have a number of problems here. Remove the ampersand highlighted in bold since you are attempting to reference a function local variable that is popped of the stack when the function returns (this constitutes undefined behaviour), therefore you should return by value.
Code:
size_t& YDim()
{
size_t i=-1; // General purpose loop variables
if(mMatrix!=0)
for(i=0; mMatrix[i]!=0;i++)
if(mMatrix[i][0]== (T) -1) break;
return i;
}
Also make the function into a const function i.e.
Code:
size_t YDim() const
{
size_t i=-1; // General purpose loop variables
if(mMatrix!=0)
for(i=0; mMatrix[i]!=0;i++)
if(mMatrix[i][0]== (T) -1) break;
return i;
}
Repeat the above two steps for XDim.
Also, you should modify your operator() function by adding the ampersand highlighted in bold since users of your class would intitively expect it to return by reference, so they can modify the value in the array:
Code:
T& operator()(size_t row, size_t col)
{
return mMatrix[row][col];
}
You also need to add a const function version of the above:
Code:
T operator()(size_t row, size_t col) const
{
return mMatrix[row][col];
}
Note that the return of the const version purposely returns by value, alternatively you can return by const reference.
Last edited by PredicateNormative; January 14th, 2009 at 12:56 PM.
Reason: gramma
-
January 14th, 2009, 12:31 PM
#8
Re: const Class& class
I agreed with 0xC0000005 when I read his post but this code compiled fine for me even without declaring the functions const. That is odd. I didn't expect this to compile. I'm using a green hills c++ compiler.
Code:
template <typename T>
class Matrix
{
private:
T** mMatrix;
T mValue;
public:
Matrix(size_t pRows, size_t pCols, const T& value)
{
size_t i, j; // General purpose loop variables
mValue = value;
mMatrix = new T* [pRows+1]; ; // Allocate rows
for(i=0; i<pRows; i++)
mMatrix[i] = new T[pCols+1]; // Allocate columns
mMatrix[i] = new T[1]; // Allocate sentinel row
// initialize mMatrix
for(i=0; i<pRows; i++)
{
size_t j;
for(j=0; j<pCols; j++)
mMatrix[i][j] = value; // initialize column with value
mMatrix[i][j] = (T) -1; // Add sentinel to end of column
}
mMatrix[i][0] = (T) -1; // Add sentinel to last row
}
~Matrix() { Destroy(); }
void Destroy()
{
for(size_t y=0; y<YDim(); y++)
{
delete mMatrix[y];
mMatrix[y]=0;
}
delete mMatrix;
mMatrix=0;
}
size_t& YDim()
{
size_t i=-1; // General purpose loop variables
if(mMatrix!=0)
for(i=0; mMatrix[i]!=0;i++)
if(mMatrix[i][0]== (T) -1) break;
return i;
}
size_t& XDim()
{
size_t j=-1; // General purpose loop variables
if(YDim()>0)
for(j=0; mMatrix[0][j] != (T) -1; j++);
return j;
}
T operator()(size_t row, size_t col)
{
return mMatrix[row][col];
}
bool ResetRow(size_t row)
{
return ResetRowTo(row, mValue);
}
bool ResetRowTo(size_t row, T value)
{
if(YDim()!=-1 && row<YDim())
{
for(size_t j=0; mMatrix[row][j] != (T) -1; j++)
mMatrix[row][j] = value;
return 1;
}
else
return 0;
}
friend ostream& operator<<(ostream& output, const Matrix& matrix)
{
for(size_t y=0; y<matrix.YDim(); y++)
{
for(size_t x=0; x<matrix.XDim(); x++)
{
cout << matrix(y,x) << " ";
}
cout << endl;
}
return output;
}
};
Last edited by kempofighter; January 14th, 2009 at 12:36 PM.
Reason: clarification.
-
January 14th, 2009, 12:44 PM
#9
Re: const Class& class
In addition to my above comments, the lack of std:: before ostream in your operator<< function suggests that you are writing using namespace std; in your header file, and you shouldn't do this in your header file, since you may cause namespace clashes in any other code that is included in your compilation.
You seem to have some issues with your loop variables. You declare a loop variable j in your constructor, but do not use it, prefering to declare a second local j inside your initialise matrix for loop. You should get into the habit of initialising your variables.
Finally, the following code found in your constructor:
Code:
for(i=0; i<pRows; i++)
mMatrix[i] = new T[pCols+1]; // Allocate columns
mMatrix[i] = new T[1]; // Allocate sentinel row
Once your for loop finishes, you fail to increment i before assigning a new memory allocation to [I]mMatrix - this constitutes a memory leak.
You could change the above to
Code:
for(i=0; i<pRows; i++)
mMatrix[i] = new T[pCols+1]; // Allocate columns
mMatrix[++i] = new T[1]; // Allocate sentinel row
Last edited by PredicateNormative; January 14th, 2009 at 12:57 PM.
Reason: Added: You should get into the habit of initialising your variables.
-
January 14th, 2009, 12:48 PM
#10
Re: const Class& class
Originally Posted by kempofighter
I agreed with 0xC0000005 when I read his post but this code compiled fine for me even without declaring the functions const. That is odd. I didn't expect this to compile. I'm using a green hills c++ compiler.
Perhaps you forgot to print the matrix e.g? :
Code:
Matrix<int> m(5,5,0);
std::cout << m << std::endl;
If you don't use the operator<< function, the compiler is allowed to exclude it from the compilation.
-
January 14th, 2009, 02:04 PM
#11
Re: const Class& class
Originally Posted by PredicateNormative
Perhaps you forgot to print the matrix e.g? :
If you don't use the operator<< function, the compiler is allowed to exclude it from the compilation.
Good point, I tried exactly that but got a compiler error. I've never overloaded the << operator before so I didn't understand why *that* didn't compile.
Code:
int main ()
{
Matrix<int> m(5,5,0);
std::cout << m << std::endl;
return 0;
}
error #349: no operator "<<" matches these operands
operand types are: std::ostream << Matrix<int>
std::cout << m << std::endl;
I thought that the overloaded << was supposed to make that work. If I comment out the cout, the class declaration compiles (for the reason your are specifying most likely). But if I try to use the stream operator as you suggest I get this other error instead. Also, in the previous block of code that I posted I changed the input arg to non-const just to see if that line in the main function would compile that uses the overloaded <<.
Good point on the other comments. I saw similar things and the class decl does produce quite a few warnings but you have already pointed those things out. I wonder how you are able to compile that simple main function but I am not. Weird.
-
January 15th, 2009, 03:53 AM
#12
Re: const Class& class
What line is it complaining about? Have you made sure that all standard objects have std:: before them, or have you used the non-ideal solution by adding using namespace std?
Last edited by PredicateNormative; January 15th, 2009 at 03:55 AM.
-
January 15th, 2009, 07:57 AM
#13
Re: const Class& class
If you have done the above, then thinking about it, the problem is probably that technically:
Code:
template <typename T>
class Matrix
{
//...
friend ostream& operator<<(ostream& output, const Matrix& matrix)
{
for(size_t y=0; y<matrix.YDim(); y++)
{
for(size_t x=0; x<matrix.XDim(); x++)
{
std::cout << matrix(y,x) << " ";
}
std::cout << std::endl;
}
return output;
}
};
is incorrect, and should be
Code:
template <typename T>
class Matrix
{
//...
template <typename U>
friend std::ostream& operator<<(std::ostream& output, const Matrix<U>& matrix);
};
template <typename U>
std::ostream& operator<<(std::ostream& output, const Matrix<U>& matrix)
{
for(size_t y=0; y<matrix.YDim(); y++)
{
for(size_t x=0; x<matrix.XDim(); x++)
{
std::cout << matrix(y,x) << " ";
}
std::cout << std::endl;
}
return output;
}
-
January 15th, 2009, 01:54 PM
#14
Re: const Class& class
Thanks predicate, I was wondering about that declaration. However, the compiler error didn't change at all. Then I noticed something awfully strange about that overloaded << operator function. Something about it isn't correct.
The OP defined the function within the class which is incorrect. It needs to be declared as a friend but defined globally.
Also, the OP uses cout within the definition. That is also wrong. He needs to be doing it like this:
Code:
template <typename T>
class Matrix
{
// ... declaration of class
// declare the globally defined function to be a friend but don't define it
// in the class. Actually i don't think that this is necessary since the
// function uses Matrix's public interface but this is the pattern I see
// when studying existing code. I guess that this is done so that the
// function definition can directly access private/protected members.
template <typename T>
friend ostream& operator<<(ostream& output, Matrix<T>& matrix);
};
// (U) Define the function globally
template <typename T>
ostream& operator<<(ostream& output, Matrix<T>& matrix)
{
for(size_t y=0; y<matrix.YDim(); y++)
{
for(size_t x=0; x<matrix.XDim(); x++)
{
// (U) Stream to output not cout
output << matrix(y,x) << " ";
}
// (U) Stream to output not cout
output << std::endl;
}
return output;
}
Well anyway, making those fixes seemed to work. The program compiled and printed a matrix full of zeroes. There are other warnings and problems with the program but at least those changes allowed the stream operator to work.
-
January 15th, 2009, 02:00 PM
#15
Re: const Class& class
Perhaps you should re-read the end of post #13
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|