My code:
#include <iostream>
using std::cin;
using std::cout;
using std::istream;
using std::ostream;
template<typename T>
class Complex
{
T real, img;
public:
Complex():real(0), img(0){}
friend istream& operator>>(istream& input, Complex& c1);
friend ostream& operator<<(ostream& output, Complex& c1);
Complex operator (Complex& c1);
};
template<typename T>
istream& operator>>(istream& input, Complex<T>& c1)
{
cout<<"Real: ";
input>>c1.real;
cout<<"Imag: ";
input>>c1.img;
return input;
}
template<typename T>
ostream& operator<<(ostream& output, Complex<T>& c1)
{
output<<c1.real<<" "<<c1.img<<"i";
return output;
}
template<typename T>
Complex<T> Complex<T>::operator (Complex<T>& c1)
{
Complex temp;
temp.real = this->real c1.real;
temp.img = this->img c1.img;
return temp;
}
int main()
{
Complex<int> cmp1;
cin>>cmp1;
return 0;
}
The error I'm getting is at cin>>cmp1
which is undefined reference to 'operator>>(std::istream&, Complex<int>&)'
. But I can't find anything wrong in my code.
The code works if I make complex a non-template class which uses double and remove all template-related code, so the definition of operator>>()
is essentially correct.
What changes when I make Complex
a template?
CodePudding user response:
Friend functions are not members so they aren't implicitly templates. Declaration there suggests existence of non-template operator for instantiated type Complex<int>
.
You may use
template<typename U>
friend istream& operator>>(istream& input, Complex<U>& c1);
template<typename U>
friend ostream& operator<<(ostream& output, Complex<U>& c1);
CodePudding user response:
The problem is that currently the overloaded friend functions are ordinary functions. If you want to make them as function templates instead then you need to change the friend declarations inside the class to as shown below.
To be more formal, in your original code operator<<
and operator>>
for class template Complex<>
are not function templates, but “ordinary” functions instantiated with the class template if needed. That is, they are templated entities.
There are 2 solutions to the problem both of which are given below.
Solution 1
template<typename T>
class Complex
{
//other members as before
//friend declarations
template<typename U>
friend istream& operator>>(istream& input, Complex<U>& c1);
template<typename V>
friend ostream& operator<<(ostream& output, Complex<V>& c1);
//other members as before
};
Solution 2
//forward declarations
template<typename T>
class Complex;
template<typename U>
istream& operator>>(istream& input, Complex<U>& c1);
template<typename V>
ostream& operator<<(ostream& output,const Complex<V>& c1);
template<typename T>
class Complex
{
T real, img;
public:
Complex():real(0), img(0){}
//friend declarations
friend istream& operator>> <T>(istream& input, Complex<T>& c1);
friend ostream& operator<< <T>(ostream& output,const Complex<T>& c1);
Complex operator (Complex& c1);
};