I am trying to output a template class to 'cout' but my code doesn't
compile; here is gcc's error message:
/tmp/ccnNaceV.o: In function `main':
main.cpp:(.text+0x6d): undefined reference to
`std::basic_ostream<char, std::char_traits<char> >& operator<<
<char>(std::basic_ostream<char, std::char_traits<char> >&,
Sudoku<char>&)'
collect2: ld returned 1 exit status
and here is the code:
157 template<class T>
158 ostream& operator<<(ostream& os, const Sudoku<T>& s)
159 {
160 for (char i=0; i < s.size; i++)
161 {
162 for (char j=0; j < s.size; j++)
163 {
164 if ( s.is_true(i, j) && HAS_BOLD )
165 {
166 os << "\033[1m" << s.get(i,j) << "\033[0m\t";
167 }
168 else
169 os << s.matrix->at(i,j) << "\t";
170 }
171 os << "\n";
172 }
173 return os;
174 }
175
176 int main()
177 {
178 Sudoku<char> s;
179 //cout << s;
180 operator<<(cout, s);
181 return 0;
182 }
I have declared
friend ostream& operator<<(ostream& os, Sudoku<T2>& s);
in the template class Sudoku.
Thanks.
Read the two declarations carefully and see if you can notice any
difference[s].
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Well, to be precise, it compiles. Your problem is that it doesn't
link. Please post sufficient, self contained code that reproduces the
same problem, so that people can copy, paste and test it to help you,
with reference to http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8
Cheers,
Francesco
If you are talking about the T2 instead of T; I had to make that
change because to was already declared as the template class of
the Sudoku class so I had to change it.
I am quite shure this is not the origin of the problem.
but thanks.
compiled with
g++ main.cpp -o main -W -Wall
Here is the entire code:
#include <iostream>
#include <assert.h>
#include <math.h>
#define HAS_BOLD 1
using namespace std;
template<class T> class SimpleMatrix
{
public:
SimpleMatrix(int x, int y) : sizex(x), sizey(y)
{
matrix = new T[x*y];
}
T& at(int x, int y)
{
assert( x < sizex );
assert( y < sizey );
return &matrix[x*sizey + sizex];
}
void set(int x, int y, T s)
{
assert( x < sizex );
assert( y < sizey );
this.at(x, y) = s;
}
void set_all(T s)
{
int size = sizex*sizey;
for (int i=0; i<size; i++)
{
matrix[i] = s;
}
}
private:
T *matrix;
int sizex;
int sizey;
};
template<class T> class Sudoku
{
template<class T2>
friend ostream& operator<<(ostream& os, Sudoku<T2>& s);
public:
Sudoku() : size(9)
{
matrix = new SimpleMatrix<T>(9,9);
truthMatrix = new SimpleMatrix<char>(9,9);
sqrtSize = (T)sqrt(size);
assert( (double)sqrtSize == sqrt(size) );
//T must be a signed type:
assert( (T)(-1) == (int)(-1) );
matrix->set_all(-1);
truthMatrix->set_all(0);
}
T get(T x, T y)
{
return *matrix->at(x,y);
}
char is_true(T x, T y)
{
return *truthMatrix->at(x,y);
}
char set(T x, T y, T s)
{
assert( x < size );
assert( y < size );
if ( !(is_true(x, y)) )
matrix->set(x, y, s);
else
return -1;
return 0;
}
void set_as_true(T x, T y, T s)
{
matrix->set(x, y, s);
truthMatrix->set(x, y, 1);
}
T get_section(T x)
//sections go from 1 to $size
{
return (T)ceil( (double)x / (double)sqrtSize );
}
T* test_coherence(T x, T y)
{
//check lines and columns:
for (T i=0; i < size; i++)
{
if ( matrix->at(i,y) == matrix->at(x,y) && &matrix->at(i,y) !=
&matrix->at(x,y) )
{
return &matrix->at(i,y);
}
else if ( matrix->at(x,i) == matrix->at(x,y) && &matrix->at(x,i) !=
&matrix->at(x,y) )
{
return &matrix->at(x,i);
}
}
//check submatrix:
T sx = get_section(x);
T sy = get_section(y);
T minx = (sx-1)*sqrtSize;
T miny = (sy-1)*sqrtSize;
T maxx = sx*sqrtSize;
T maxy = sy*sqrtSize;
for (T i=minx; i < maxx; i++)
{
for (T j=miny; j < maxy; j++)
{
if (matrix->at(i,j) == matrix->at(x,y) && &matrix->at(x,y) !=
&matrix->at(i,j))
{
return &matrix->at(i,j);
}
}
}
return (T)(-1);
}
private:
SimpleMatrix<T> *matrix;
SimpleMatrix<char> *truthMatrix;
T size;
T sqrtSize;
void set_matrix(T* matrix, T c)
{
for (T i=0; i < size; i++)
{
for (T j=0; j<size; j++)
{
matrix->at(i,j) = c;
}
}
}
};
/*
istream& operator>>(istream& is, Sudoku<T>& s)
{
return NULL;
}
*/
template<class T>
ostream& operator<<(ostream& os, const Sudoku<T>& s)
{
for (char i=0; i < s.size; i++)
{
for (char j=0; j < s.size; j++)
{
if ( s.is_true(i, j) && HAS_BOLD )
{
os << "\033[1m" << s.get(i,j) << "\033[0m\t";
}
else
os << s.matrix->at(i,j) << "\t";
}
os << "\n";
}
return os;
}
int main()
{
Sudoku<char> s;
//cout << s;
operator<<(cout, s);
return 0;
}
Look at it again, and see if you don't see another difference -- a
word (a keyword) that's present in one, but not the other...
--
Later,
Jerry.
I indeed forgot the 'const'. That was a pretty stupid mistake.
I think I can now solve my problem by adding a few other 'const's
that I forgot.
Thank you.
Fine, now that you have solved that issue, please note that there are
several other points you can fix/improve:
- the C-style casts
- the use of #define
- the possible memory leak due to your use of operator new
- the test for signed types (use the functions found in <limits>
instead)
Refer to the FAQ I linked and you'll find solutions to most of your
issues, along with their rationales.
Keep improving your code,
cheers,
Francesco