Template member function help.



 DEVELOP > c-Plus-Plus > Template member function help.

LINK TO THIS PAGE  


rating :  0   |  0


  Page 1 of 1

1

 
Topic: DEVELOP > c-Plus-Plus
User: "Jason"
Date: 17 Oct 2006 12:31:36 PM
Object: Template member function help.
/*
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<typename DataType> void SimpleMatrix< SimpleMatrix<DataType>

::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, but now only when submatrices has type of SimpleMatrix<int>
template<> void SimpleMatrix< SimpleMatrix<int>

::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;
}
.

User: ""

Title: Re: Template member function help. 17 Oct 2006 12:46:01 PM
Jason wrote:

/*
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<typename DataType> void SimpleMatrix< SimpleMatrix<DataType>

::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, but now only when submatrices has type of SimpleMatrix<int>
template<> void SimpleMatrix< SimpleMatrix<int>

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

User: ""

Title: Re: Template member function help. 17 Oct 2006 12:46:16 PM
Jason wrote:

/*
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<typename DataType> void SimpleMatrix< SimpleMatrix<DataType>

::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, but now only when submatrices has type of SimpleMatrix<int>
template<> void SimpleMatrix< SimpleMatrix<int>

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

User: "Victor Bazarov"

Title: Re: Template member function help. 17 Oct 2006 12:58:14 PM
Jason wrote:

/*
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<typename DataType> void SimpleMatrix< SimpleMatrix<DataType>

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>::out(os, *this);
}
};
template<class T>
void Blah_Printer<T>::out(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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
.
User: "Jason"

Title: Re: Template member function help. 17 Oct 2006 02:42:42 PM
On Oct 17, 10:58 am, "Victor Bazarov" <v.Abaza...@comAcast.net> wrote:

Jason wrote:

/*
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<typename DataType> void SimpleMatrix< SimpleMatrix<DataType>

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>::out(os, *this);
}
};

template<class T>
void Blah_Printer<T>::out(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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask- Hide quoted text -- Show quoted text -

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



  Page 1 of 1

1

 


Related Articles
 

NEWER

pg.1232     pg.940     pg.716     pg.544     pg.412     pg.311     pg.234     pg.175     pg.130     pg.96     pg.70     pg.50     pg.35     pg.24     pg.16     pg.10     pg.6     pg.3     pg.1

OLDER