new way of overloading operators in templates??
First of all, this code does compile with g++ 3.3.5. But with g++ 4.0.2 it gives me a few errors. g++ enters the #else portion. The _MSC_VER is meant to be able to compile it in VC++ 5
Code:
#ifdef _MSC_VER
friend CMatriz<TG> operator+(const TG &op1,const CMatriz<TG> op2); // objeto TG + CMatriz
friend CMatriz<TG> operator+(const double &op1,const CMatriz<TG> &op2); // constante + CMatriz
#else /*Next line is 64*/
friend CMatriz<TG> operator+ <>(const TG &op1,const CMatriz<TG> &op2); // objeto TG + CMatriz
friend CMatriz<TG> operator+ <>(const double &op1,const CMatriz<TG> &op2); // constante + CMatriz
#endif
The compiler says:
Matriz.h:64: error: declaration of 'operator+' as non-function
This error happens too with another operators. However with the <<:
Code:
#ifdef _MSC_VER
friend ostream &operator<<(ostream &os,const CMatriz<TG> &op);
#else /*Next line is 87*/
friend ostream &operator<< <>(ostream &os,const CMatriz<TG> &op);
#endif
The compiler gives a different error:
Matriz.h:87: error: template-id 'operator<< <>' for std::basic_ostream<char, std::char_traits<char> >& operator<<(std::basic_ostream<char, std::char_traits<char> >&, const CMatriz<CComplejo>&)' does not match any template declaration
Any clues as to how should these be declared?
Re: new way of overloading operators in templates??
For the record, I solved the ostream << problem by adding:
Code:
template<class TG> class CMatriz;
template<class TG> ostream& operator<< (ostream & os, const CMatriz<TG> &op);
Before declaring the template class. I haven't found the way to fix it for the other operators.
Re: new way of overloading operators in templates??
Maybe for friend declarations you should try this:
Code:
template< class W >
friend CMatriz<W> operator+ (const W &op1,const CMatriz<W> &op2); // objeto W + CMatriz
template< class W >
friend CMatriz<W> operator+ (const double &op1, const CMatriz<W> &op2); // constante + CMatriz
I hope it helps.
Re: new way of overloading operators in templates??
What are the empty angle brackets doing?
Re: new way of overloading operators in templates??
In order to use the <> versions, declarations of the templates in question have to be visible. So you need:
Code:
template<class TG> class CMatriz;
template<class TG> ostream& operator<< (ostream & os, const CMatriz<TG> &op);
template< class W >
CMatriz<W> operator+ (const W &op1,const CMatriz<W> &op2);
template< class W >
CMatriz<W> operator+ (const double &op1, const CMatriz<W> &op2);
template<class TG> class CMatriz
{
//friends, etc.
};
Also, the friend declarations would be more explicit if you specified the template argument, rather than leaving it up to template argument deduction. e.g.
Code:
friend CMatriz<TG> operator+ <TG>(const double &op1,const CMatriz<TG> &op2);
Re: new way of overloading operators in templates??
Quote:
Originally Posted by Graham
What are the empty angle brackets doing?
If you don't have them, the compiler assumes that the friend declaraton refers to a non-template function from the surrounding namespace, so the template function that is supposed to be a friend isn't made one.
Re: new way of overloading operators in templates??
Many thanks for the help, I've done what you said but it still gives the same errors.
This is how it looks now:
Code:
template<class TG> class CMatriz;
template<class TG> ostream& operator<< (ostream & os, const CMatriz<TG> &op);
template<class TG> CMatriz<TG> operator+ (const TG &op1,const CMatriz<TG> &op2); // objeto TG + CMatriz
template<class TG> CMatriz<TG> operator+ (const double &op1,const CMatriz<TG> &op2); // constante + CMatriz
template<class TG> CMatriz<TG> operator* (const TG &op1,const CMatriz<TG> &op2); // Objeto TG por matriz
template<class TG> CMatriz<TG> operator* (const double &op1,const CMatriz<TG> &op2); // Constante por matriz
template<class TG> class CMatriz
{
public:
CMatriz(unsigned int j=1,unsigned int k=1);
CMatriz(const CMatriz<TG> &cpv);
~CMatriz();
// Other stuff here
//....... below is line 74
friend CMatriz<TG> operator+ <>(const TG &op1,const CMatriz<TG> &op2); // objeto TG + CMatriz
friend CMatriz<TG> operator+ <>(const double &op1,const CMatriz<TG> &op2); // constante + CMatriz
//....... below is line 90
friend CMatriz<TG> operator* <>(const TG &op1,const CMatriz<TG> &op2); // Objeto TG por matriz
friend CMatriz<TG> operator* <>(const double &op1,const CMatriz<TG> &op2); // Constante por matriz
//.......
protected:
//.......
}
/** Other functions
.....
*/
template<class TG>
CMatriz<TG> operator+(const TG &op1,const CMatriz<TG> &op2)
{
unsigned int j,k;
CMatriz<TG> suma(op2.m_reng,op2.m_cols);
for(j=0;j<op2.m_reng;j++)
for(k=0;k<op2.m_cols;k++)
suma.inserta(j,k,op2.obten(j,k)+op1);
return suma;
}
The errors reported:
Code:
legg@lc65:~/tempo$ make
g++ -O -g -I. -DLinux -Wall -c main.cpp
Matriz.h:74: error: declaration of 'operator+' as non-function
Matriz.h:74: error: expected ';' before '<' token
Matriz.h:75: error: declaration of 'operator+' as non-function
Matriz.h:75: error: expected ';' before '<' token
Matriz.h:90: error: declaration of 'operator*' as non-function
Matriz.h:90: error: expected ';' before '<' token
Matriz.h:91: error: declaration of 'operator*' as non-function
Matriz.h:91: error: expected ';' before '<' token
Matriz.h: In function 'CMatriz<TG> operator*(const double&, const CMatriz<TG>&) [with TG = int]':
main.cpp:39: instantiated from here
Matriz.h:102: error: 'unsigned int CMatriz<int>::m_reng' is protected
Matriz.h:354: error: within this context
Matriz.h:102: error: 'unsigned int CMatriz<int>::m_cols' is protected
Matriz.h:354: error: within this context
Matriz.h:102: error: 'unsigned int CMatriz<int>::m_reng' is protected
Matriz.h:355: error: within this context
Matriz.h:102: error: 'unsigned int CMatriz<int>::m_cols' is protected
Matriz.h:356: error: within this context
Matriz.h: In function 'CMatriz<TG> operator*(const double&, const CMatriz<TG>&) [with TG = CComplejo]':
main.cpp:87: instantiated from here
Matriz.h:102: error: 'unsigned int CMatriz<CComplejo>::m_reng' is protected
Matriz.h:354: error: within this context
Matriz.h:102: error: 'unsigned int CMatriz<CComplejo>::m_cols' is protected
Matriz.h:354: error: within this context
Matriz.h:102: error: 'unsigned int CMatriz<CComplejo>::m_reng' is protected
Matriz.h:355: error: within this context
Matriz.h:102: error: 'unsigned int CMatriz<CComplejo>::m_cols' is protected
Matriz.h:356: error: within this context
make: *** [main.o] Error 1
The protected errors are spurious (should be).
If I include a declaration like:
Code:
friend CMatriz<TG> operator* <TG>(const double &op1,const CMatriz<TG> &op2); // Constante por matriz
It won't compile under 3.3 either.
Re: new way of overloading operators in templates??
I found out. The correct code is:
Code:
#ifdef _MSC_VER
friend CMatriz<TG> operator+(const TG &op1,const CMatriz<TG> &op2); // objeto TG + CMatriz
friend CMatriz<TG> operator+(const double &op1,const CMatriz<TG> &op2); // constante + CMatriz
#elif __GNUC__ > 3 || (__GNUC__==3 && __GNUC_MINOR__ >=4)
friend CMatriz<TG> (::operator+ <TG>)(const TG &op1,const CMatriz<TG> &op2); // objeto TG + CMatriz
friend CMatriz<TG> (::operator+ <TG>)(const double &op1,const CMatriz<TG> &op2); // constante + CMatriz
#else
friend CMatriz<TG> operator+ <>(const TG &op1,const CMatriz<TG> &op2); // objeto TG + CMatriz
friend CMatriz<TG> operator+ <>(const double &op1,const CMatriz<TG> &op2); // constante + CMatriz
#endif
The code I was after is the one meant for gcc>=3.4, that however won't compile in 3.3
Any idea as to what does the new code means? :confused:
Re: new way of overloading operators in templates??
Quote:
Originally Posted by Graham
What are the empty angle brackets doing?
Assuming we are referring to the same thing, I am sure you know why you use empty angle brackets in template friend specifications.
Code:
template < typename T > class Matriz;
template < typename T > std::ostream &
operator<< ( std::ostream &, const Matriz< T > & );
template < typename T >
class Matriz
{
friend std::ostream & operator<< <> ( std::ostream &, const Matriz & );
// rest of template Matriz
};
template < typename T >
std::ostream & operator<< ( std::ostream & os, const Matriz<T> & mat )
{
// implement here
}
The angled brackets in friend declaration tell the compiler that it is a template function.
Re: new way of overloading operators in templates??
I was suggesting looking into the reason why they were there in one conditional section, but not in the other (unless it was down to compiler silliness - which seems probable, given mention of VC5).
Mind you, I rarely use friends, and I don't think I've ever coded a template friend...