Home > Back-end >  "undefined reference to `operator>>(std::istream&, Complex<int>&)" for templat
"undefined reference to `operator>>(std::istream&, Complex<int>&)" for templat

Time:03-18

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

Demo

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);
};

Demo

  • Related