"undefined reference to `operator>>(std::istream&, Complex<int>&)" 模板复杂<T>

"undefined reference to `operator>>(std::istream&, Complex<int>&)" for template Complex<T>

我的代码:

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

我得到的错误是 cin>>cmp1,即 undefined reference to 'operator>>(std::istream&, Complex<int>&)'。但是我在我的代码中找不到任何错误。

如果我将复杂的非模板 class 设为 double 并删除所有与模板相关的代码,则代码有效,因此 operator>>() 的定义基本上是正确的。

当我制作 Complex 模板时有什么变化?

友元函数不是成员,因此它们不是隐式模板。那里的声明表明实例化类型 Complex<int> 存在 non-template 运算符。 您可以使用

template<typename U> 
friend istream& operator>>(istream& input, Complex<U>& c1);

template<typename U> 
friend ostream& operator<<(ostream& output, Complex<U>& c1);

问题是目前重载的友元函数是普通函数。如果你想让它们成为函数模板,那么你需要将 class 中的 friend declarations 更改为如下所示。

更正式地说,在您的原始代码中,operator<<operator>> 用于 class 模板 Complex<> 不是函数模板,而是“普通”函数 如果需要,使用 class 模板实例化 。也就是说,它们是模板化实体

有 2 种方法可以解决这个问题,下面给出了两种方法。

解决方案 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

解决方案 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