operator<< with template class doesn't work

W

Wolfnoliir

Hi,

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.
 
V

Victor Bazarov

Wolfnoliir said:
[..] and here is the code:

157 template<class T>
158 ostream& operator<<(ostream& os, const Sudoku<T>& s)

friend ostream& operator<<(ostream& os, Sudoku<T2>& s);

Read the two declarations carefully and see if you can notice any
difference.

V
 
F

Francesco

Hi,

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.

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
 
W

Wolfnoliir

Victor said:
Wolfnoliir said:
[..] and here is the code:

157 template<class T>
158 ostream& operator<<(ostream& os, const Sudoku<T>& s)

friend ostream& operator<<(ostream& os, Sudoku<T2>& s);

Read the two declarations carefully and see if you can notice any
difference.

V


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.
 
W

Wolfnoliir

Francesco said:
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

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 = 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;
}
 
J

Jerry Coffin

Victor said:
Wolfnoliir said:
[..] and here is the code:

157 template<class T>
158 ostream& operator<<(ostream& os, const Sudoku<T>& s)

friend ostream& operator<<(ostream& os, Sudoku<T2>& s);

Read the two declarations carefully and see if you can notice any
difference.

V


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.


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...
 
W

Wolfnoliir

Jerry said:
Victor said:
Wolfnoliir wrote:
[..] and here is the code:

157 template<class T>
158 ostream& operator<<(ostream& os, const Sudoku<T>& s)

friend ostream& operator<<(ostream& os, Sudoku<T2>& s);
Read the two declarations carefully and see if you can notice any
difference.

V

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.


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...


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.
 
F

Francesco

Jerry said:
Victor Bazarov wrote:
Wolfnoliir wrote:
[..] and here is the code:
157 template<class T>
158 ostream& operator<<(ostream& os, const Sudoku<T>& s)
friend ostream& operator<<(ostream& os, Sudoku<T2>& s);
Read the two declarations carefully and see if you can notice any
difference.
V
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.

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...

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top