Template member function help.

J

Jason

/*
I have never use template before, so bear with me.

Here is what I am trying to do:

I declare an abstract base class MatrixInterface with template to
define an interface for all my subsequent Matrix class. In
MatrixInterface class, I overloaded the << operator by calling a pure
virtual function PrintDebugMessage(ostream &os); then I can implement
the function on individual Matrix classes later.

I create a Matrix class called SimpleMatrix, and implemented
PrintDebugMessage(). Everthing works great until I want to implement
different behavior depending whether it's

template<typename DataType> void
SimpleMatrix<DataType>::printDebugMessage(...); //this is fine

or

//error
template said:
::printDebugMessage(...);

I want to print out data differently if a instance of my SimpleMatrix
is a collection of sub-matrices of type SimpleMatrix. However, I can't
get that to work.

If I sepcialize the template parameter like:

// works said:
::printDebugMessage(...);

then it works. How I generalize the function above to handle
SimpleMatrice submatrix of all type?


Below is a sample code of my problem. It compiles on gcc 3.2.3 and
intel c++ 8.1
*/
/********************************************

********************************************/
#include <iostream>
#include <typeinfo>

using namespace std;

/************************************
** ABC for all Matrix class
*************************************/
template<typename DataType>
class MatrixInterface
{
public:
template<typename T>
friend ostream & operator<<(ostream &os, MatrixInterface<T> const &
matrix);
protected:
virtual void PrintDebugMessage(ostream &os) const= 0;

};

template<typename DataType>
ostream & operator<<(ostream &os, MatrixInterface<DataType> const
&matrix)
{
matrix.PrintDebugMessage(os);
return os;
}
/************************************
** Simple Matrix
*************************************/
template<typename DataType>
class SimpleMatrix:public MatrixInterface<DataType>
{
public:
SimpleMatrix();
SimpleMatrix(size_t nrow, size_t ncol);
virtual ~SimpleMatrix();
protected:

virtual void PrintDebugMessage(ostream &os) const;

size_t m_rowSize, m_colSize;
DataType *m_data;


};
//
//
template<typename DataType>
SimpleMatrix<DataType>::SimpleMatrix()
:m_rowSize(0), m_colSize(0),
m_data(0)
{
}
//
//
template<typename DataType>
SimpleMatrix<DataType>::SimpleMatrix(size_t nrow, size_t ncol)
:m_rowSize(nrow), m_colSize(ncol),
m_data(0)
{
if(m_rowSize*m_colSize>0) m_data =new
DataType[m_rowSize*m_colSize];
}
//
//
template<typename DataType>
SimpleMatrix<DataType>::~SimpleMatrix()
{
if(m_data != 0) delete [] m_data;
}
//
// Default PrintDebugMessage
//
template<typename DataType>
void SimpleMatrix<DataType>::printDebugMessage(ostream &os) const
{
size_t index;
cout << typeid(DataType).name()<<"[ ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "]";
}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* I want PrintDebugMessage to behave differently
* when I when the m_data submatrice of type = SimpleMatrix<T> where T
* can be anything.
*
* Doesn't work :(
*
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/*
template<typename T>
void SimpleMatrix< SimpleMatrix<T> >::printDebugMessage(ostream &os)
const
{
size_t index;
cout << typeid(SimpleMatrix<int>).name()<<"[[[[ ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "]]]]";
}
*/


/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* This works. Don't really get it.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
template<>
void SimpleMatrix< SimpleMatrix<int> >::printDebugMessage(ostream &os)
const
{
size_t index;
cout << "< "<<typeid(SimpleMatrix<int>).name()<< " > "<<"//** ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "**//";
}




/******************
******************/
int main(int argc, char **argv)
{
SimpleMatrix<int> IntMatrix(3,3);
SimpleMatrix<double> DoubleMatrix(2,2);
SimpleMatrix< SimpleMatrix<int> > IntMatrixMatrix(2,2);
SimpleMatrix< SimpleMatrix<double> > DoubleMatrixMatrix(2,2);
cout<<IntMatrix<<endl;
cout<<DoubleMatrix<<endl;
cout<<IntMatrixMatrix<<endl;
cout<<DoubleMatrixMatrix<<endl; //use wrong Print function
return 0;
}
 
A

amparikh

Jason said:
/*
I have never use template before, so bear with me.

Here is what I am trying to do:

I declare an abstract base class MatrixInterface with template to
define an interface for all my subsequent Matrix class. In
MatrixInterface class, I overloaded the << operator by calling a pure
virtual function PrintDebugMessage(ostream &os); then I can implement
the function on individual Matrix classes later.

I create a Matrix class called SimpleMatrix, and implemented
PrintDebugMessage(). Everthing works great until I want to implement
different behavior depending whether it's

template<typename DataType> void
SimpleMatrix<DataType>::printDebugMessage(...); //this is fine

or

//error
template said:
::printDebugMessage(...);

I want to print out data differently if a instance of my SimpleMatrix
is a collection of sub-matrices of type SimpleMatrix. However, I can't
get that to work.

If I sepcialize the template parameter like:

// works said:
::printDebugMessage(...);

then it works. How I generalize the function above to handle
SimpleMatrice submatrix of all type?


Below is a sample code of my problem. It compiles on gcc 3.2.3 and
intel c++ 8.1
*/
/********************************************

********************************************/
#include <iostream>
#include <typeinfo>

using namespace std;

/************************************
** ABC for all Matrix class
*************************************/
template<typename DataType>
class MatrixInterface
{
public:
template<typename T>
friend ostream & operator<<(ostream &os, MatrixInterface<T> const &
matrix);
protected:
virtual void PrintDebugMessage(ostream &os) const= 0;

};

template<typename DataType>
ostream & operator<<(ostream &os, MatrixInterface<DataType> const
&matrix)
{
matrix.PrintDebugMessage(os);
return os;
}
/************************************
** Simple Matrix
*************************************/
template<typename DataType>
class SimpleMatrix:public MatrixInterface<DataType>
{
public:
SimpleMatrix();
SimpleMatrix(size_t nrow, size_t ncol);
virtual ~SimpleMatrix();
protected:

virtual void PrintDebugMessage(ostream &os) const;

size_t m_rowSize, m_colSize;
DataType *m_data;


};
//
//
template<typename DataType>
SimpleMatrix<DataType>::SimpleMatrix()
:m_rowSize(0), m_colSize(0),
m_data(0)
{
}
//
//
template<typename DataType>
SimpleMatrix<DataType>::SimpleMatrix(size_t nrow, size_t ncol)
:m_rowSize(nrow), m_colSize(ncol),
m_data(0)
{
if(m_rowSize*m_colSize>0) m_data =new
DataType[m_rowSize*m_colSize];
}
//
//
template<typename DataType>
SimpleMatrix<DataType>::~SimpleMatrix()
{
if(m_data != 0) delete [] m_data;
}
//
// Default PrintDebugMessage
//
template<typename DataType>
void SimpleMatrix<DataType>::printDebugMessage(ostream &os) const
{
size_t index;
cout << typeid(DataType).name()<<"[ ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "]";
}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* I want PrintDebugMessage to behave differently
* when I when the m_data submatrice of type = SimpleMatrix<T> where T
* can be anything.
*
* Doesn't work :(
*
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/*
template<typename T>
void SimpleMatrix< SimpleMatrix<T> >::printDebugMessage(ostream &os)
const
{
size_t index;
cout << typeid(SimpleMatrix<int>).name()<<"[[[[ ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "]]]]";
}
*/


/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* This works. Don't really get it.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
template<>
void SimpleMatrix< SimpleMatrix<int> >::printDebugMessage(ostream &os)
const
{
size_t index;
cout << "< "<<typeid(SimpleMatrix<int>).name()<< " > "<<"//** ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "**//";
}




/******************
******************/
int main(int argc, char **argv)
{
SimpleMatrix<int> IntMatrix(3,3);
SimpleMatrix<double> DoubleMatrix(2,2);
SimpleMatrix< SimpleMatrix<int> > IntMatrixMatrix(2,2);
SimpleMatrix< SimpleMatrix<double> > DoubleMatrixMatrix(2,2);
cout<<IntMatrix<<endl;
cout<<DoubleMatrix<<endl;
cout<<IntMatrixMatrix<<endl;
cout<<DoubleMatrixMatrix<<endl; //use wrong Print function
return 0;
}


Well, you first need to either explicity partially specialize the class
for that type(SimpleMatirx<T> and then use PrintDebugMessage the way
you have used it.

Remember the class is a template class. PrintDebugMessafe is NOT a
member template.
 
A

amparikh

Jason said:
/*
I have never use template before, so bear with me.

Here is what I am trying to do:

I declare an abstract base class MatrixInterface with template to
define an interface for all my subsequent Matrix class. In
MatrixInterface class, I overloaded the << operator by calling a pure
virtual function PrintDebugMessage(ostream &os); then I can implement
the function on individual Matrix classes later.

I create a Matrix class called SimpleMatrix, and implemented
PrintDebugMessage(). Everthing works great until I want to implement
different behavior depending whether it's

template<typename DataType> void
SimpleMatrix<DataType>::printDebugMessage(...); //this is fine

or

//error
template said:
::printDebugMessage(...);

I want to print out data differently if a instance of my SimpleMatrix
is a collection of sub-matrices of type SimpleMatrix. However, I can't
get that to work.

If I sepcialize the template parameter like:

// works said:
::printDebugMessage(...);

then it works. How I generalize the function above to handle
SimpleMatrice submatrix of all type?


Below is a sample code of my problem. It compiles on gcc 3.2.3 and
intel c++ 8.1
*/
/********************************************

********************************************/
#include <iostream>
#include <typeinfo>

using namespace std;

/************************************
** ABC for all Matrix class
*************************************/
template<typename DataType>
class MatrixInterface
{
public:
template<typename T>
friend ostream & operator<<(ostream &os, MatrixInterface<T> const &
matrix);
protected:
virtual void PrintDebugMessage(ostream &os) const= 0;

};

template<typename DataType>
ostream & operator<<(ostream &os, MatrixInterface<DataType> const
&matrix)
{
matrix.PrintDebugMessage(os);
return os;
}
/************************************
** Simple Matrix
*************************************/
template<typename DataType>
class SimpleMatrix:public MatrixInterface<DataType>
{
public:
SimpleMatrix();
SimpleMatrix(size_t nrow, size_t ncol);
virtual ~SimpleMatrix();
protected:

virtual void PrintDebugMessage(ostream &os) const;

size_t m_rowSize, m_colSize;
DataType *m_data;


};
//
//
template<typename DataType>
SimpleMatrix<DataType>::SimpleMatrix()
:m_rowSize(0), m_colSize(0),
m_data(0)
{
}
//
//
template<typename DataType>
SimpleMatrix<DataType>::SimpleMatrix(size_t nrow, size_t ncol)
:m_rowSize(nrow), m_colSize(ncol),
m_data(0)
{
if(m_rowSize*m_colSize>0) m_data =new
DataType[m_rowSize*m_colSize];
}
//
//
template<typename DataType>
SimpleMatrix<DataType>::~SimpleMatrix()
{
if(m_data != 0) delete [] m_data;
}
//
// Default PrintDebugMessage
//
template<typename DataType>
void SimpleMatrix<DataType>::printDebugMessage(ostream &os) const
{
size_t index;
cout << typeid(DataType).name()<<"[ ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "]";
}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* I want PrintDebugMessage to behave differently
* when I when the m_data submatrice of type = SimpleMatrix<T> where T
* can be anything.
*
* Doesn't work :(
*
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/*
template<typename T>
void SimpleMatrix< SimpleMatrix<T> >::printDebugMessage(ostream &os)
const
{
size_t index;
cout << typeid(SimpleMatrix<int>).name()<<"[[[[ ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "]]]]";
}
*/


/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* This works. Don't really get it.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
template<>
void SimpleMatrix< SimpleMatrix<int> >::printDebugMessage(ostream &os)
const
{
size_t index;
cout << "< "<<typeid(SimpleMatrix<int>).name()<< " > "<<"//** ";
for(index = 0; index < m_rowSize*m_colSize; ++index)
cout<<m_data[index]<<" ";
cout << "**//";
}




/******************
******************/
int main(int argc, char **argv)
{
SimpleMatrix<int> IntMatrix(3,3);
SimpleMatrix<double> DoubleMatrix(2,2);
SimpleMatrix< SimpleMatrix<int> > IntMatrixMatrix(2,2);
SimpleMatrix< SimpleMatrix<double> > DoubleMatrixMatrix(2,2);
cout<<IntMatrix<<endl;
cout<<DoubleMatrix<<endl;
cout<<IntMatrixMatrix<<endl;
cout<<DoubleMatrixMatrix<<endl; //use wrong Print function
return 0;
}


Well, you first need to either explicity partially specialize the class
for that type(SimpleMatirx<T> and then use PrintDebugMessage the way
you have used it.

Remember the class is a template class. PrintDebugMessage is NOT a
member template.
 
V

Victor Bazarov

Jason said:
/*
I have never use template before, so bear with me.

Here is what I am trying to do:

I declare an abstract base class MatrixInterface with template to
define an interface for all my subsequent Matrix class. In
MatrixInterface class, I overloaded the << operator by calling a pure
virtual function PrintDebugMessage(ostream &os); then I can implement
the function on individual Matrix classes later.

I create a Matrix class called SimpleMatrix, and implemented
PrintDebugMessage(). Everthing works great until I want to implement
different behavior depending whether it's

template<typename DataType> void
SimpleMatrix<DataType>::printDebugMessage(...); //this is fine

or

//error
[..]

What you're trying here is to specialise a member without specialising
the class first. That's prohibited, AFAIK.

Your solution lies either in specialising the entire class:

#include <iostream>
using namespace std;

template<class T> struct Blah {
void out(ostream& os) {
os << "regular Blah\n";
}
};

template<class T> struct Blah<Blah<T> > {
void out(ostream& os) {
os << "Blah of Blah\n";
}
};

int main()
{
Blah<int> bi;
Blah<double> bd;
Blah<Blah<int> > bbi;
Blah<Blah<Blah<double> > > bbbd;

bi.out(cout);
bd.out(cout);
bbi.out(cout);
bbbd.out(cout);
}

(which would require a whole lot of repetition) or in providing
a proxy "printer" class and specialising it instead (look up "policy
based design"):

#include <iostream>
using namespace std;

template<class T> struct Blah;

template<class T> struct Blah_Printer {
static void out(ostream& os, Blah<T>& blah);
};

template<class T> struct Blah {
void out(ostream& os) {
Blah_Printer<T>::eek:ut(os, *this);
}
};

template<class T>
void Blah_Printer<T>::eek:ut(ostream& os, Blah<T>& b) {
os << "regular Blah\n";
}

// partial specialisation
template<class T> struct Blah_Printer<Blah<T> > {
static void out(ostream& os, Blah<Blah<T> >& b) {
os << "Blah of Blah\n";
}
};

int main()
{
Blah<int> bi;
Blah<double> bd;
Blah<Blah<int> > bbi;
Blah<Blah<Blah<double> > > bbbd;

bi.out(cout);
bd.out(cout);
bbi.out(cout);
bbbd.out(cout);
}

Of course, 'Blah<Blah<Blah<Blah<Blah...>' is treated just like the
simply nested 'Blah<Blah<T> >' would be.

V
 
J

Jason

Jason said:
/*
I have never use template before, so bear with me.
Here is what I am trying to do:
I declare an abstract base class MatrixInterface with template to
define an interface for all my subsequent Matrix class. In
MatrixInterface class, I overloaded the << operator by calling a pure
virtual function PrintDebugMessage(ostream &os); then I can implement
the function on individual Matrix classes later.
I create a Matrix class called SimpleMatrix, and implemented
PrintDebugMessage(). Everthing works great until I want to implement
different behavior depending whether it's
template<typename DataType> void
SimpleMatrix<DataType>::printDebugMessage(...); //this is fine

//error
template said:
PrintDebugMessage(...);
[..]What you're trying here is to specialise a member without specialising
the class first. That's prohibited, AFAIK.

Your solution lies either in specialising the entire class:

#include <iostream>
using namespace std;

template<class T> struct Blah {
void out(ostream& os) {
os << "regular Blah\n";
}
};

template<class T> struct Blah<Blah<T> > {
void out(ostream& os) {
os << "Blah of Blah\n";
}
};

int main()
{
Blah<int> bi;
Blah<double> bd;
Blah<Blah<int> > bbi;
Blah<Blah<Blah<double> > > bbbd;

bi.out(cout);
bd.out(cout);
bbi.out(cout);
bbbd.out(cout);
}

(which would require a whole lot of repetition) or in providing
a proxy "printer" class and specialising it instead (look up "policy
based design"):

#include <iostream>
using namespace std;

template<class T> struct Blah;

template<class T> struct Blah_Printer {
static void out(ostream& os, Blah<T>& blah);
};

template<class T> struct Blah {
void out(ostream& os) {
Blah_Printer<T>::eek:ut(os, *this);
}
};

template<class T>
void Blah_Printer<T>::eek:ut(ostream& os, Blah<T>& b) {
os << "regular Blah\n";
}

// partial specialisation
template<class T> struct Blah_Printer<Blah<T> > {
static void out(ostream& os, Blah<Blah<T> >& b) {
os << "Blah of Blah\n";
}
};

int main()
{
Blah<int> bi;
Blah<double> bd;
Blah<Blah<int> > bbi;
Blah<Blah<Blah<double> > > bbbd;

bi.out(cout);
bd.out(cout);
bbi.out(cout);
bbbd.out(cout);
}

Of course, 'Blah<Blah<Blah<Blah<Blah...>' is treated just like the
simply nested 'Blah<Blah<T> >' would be.

V



To Victor,

Thanks for the help! Your explanation clarify my confusion over
template.
 

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,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top