Re: operator<< with template class doesn't work
Francesco wrote:
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[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;
}