C++ 模板类运算符重载的不同错误和警告问题

C++ 模板类运算符重载的不同错误和警告问题,c++,c++11,templates,C++,C++11,Templates,在重载模板类的加法运算符时,我遇到了不同的问题 我终于找到了一个解决方案,下面的代码可以毫无问题地工作 template<class T> class A; template<class T> A<T> operator + (const A<T>& , const A<T>&); template <class T> A<T> operator+ (A<T> & a1,

在重载模板类的加法运算符时,我遇到了不同的问题

我终于找到了一个解决方案,下面的代码可以毫无问题地工作

template<class T>
class A;

template<class T>
A<T> operator + (const A<T>& , const A<T>&);

template <class T>
A<T> operator+ (A<T> & a1, A<T> & a2){
    //the definition of the function
}

template <class T>
class A{
    friend A<T> operator +<> (const A<T>& , const A<T>& );
    private: //...whatever
    public: //...whatever
};
模板
甲级;
模板
运算符+(常数A&,常数A&);
模板
A运算符+(A&a1、A&a2){
//函数的定义
}
模板
甲级{
友元A运算符+(常数A&,常数A&);
二等兵:/…随便什么
公众://…随便什么
};

然而,在我对上述代码进行了一些实验之后,我感到非常困惑。

  • 我更改了类A中的友元函数声明
    朋友A操作符+(常数A&,常数A&)
    友元A运算符+(常数A&,常数A&)
    (删除
    运算符+
    后的

    然后,代码可以运行并给出结果,但我得到一个警告
    警告:友元声明“运算符+(常量a&,常量a&)”声明一个非模板函数

  • 没有在步骤1中进行修改,我删除了加法运算符重载函数的模板声明。因此,以下代码被删除:

    模板
    运算符+(常数A&,常数A&)

    然后我得到一个错误:
    error:A operator+(const A&,const A&)的模板id“operator+”与任何模板声明都不匹配

  • 我在第1步和第2步中都做了修改,然后在第1步中得到了相同的警告:
    警告:友元声明'A operator+(const A&,const A&')声明了一个非模板函数


  • 我对这些修改引起的问题感到困惑

  • 操作符+
    之后的
    效果如何?(参见第一次修改)
  • 删除加法运算符重载函数的模板声明会有什么影响?(参见第二次修改)
  • 为什么当我只进行第二次修改时,代码不能运行并返回错误,而当我进行第一次和第二次修改时,它可以运行并返回警告

  • 提前谢谢

    案例1
    友元A操作符+(常数A&,常数A&)
    实际上是类型
    T
    的以下函数的友元特化(这是类模板的类型)

    所以你的朋友函数是一个特殊的朋友函数

    当您删除
    时,您的好友函数将变为普通好友函数,但实际的
    运算符+
    是一个模板函数。编译器正在警告您,因为您的类定义具有友元函数的非模板声明(没有模板),但友元函数定义是函数模板。将您的friend函数更改为以下内容以抑制警告

    template<class T1>
    friend A<T1> operator+ (const A<T1>&, const A<T1>&);
    

    编译器找不到使用两个
    常量a&
    参数的模板函数。

    谢谢!我在
    operator+
    的定义中添加了
    const
    ,效果很好。但是我的问题中的第一个代码片段(没有修改1或2)在其
    操作符+
    定义中仍然没有
    常量,而在其声明中有
    常量。为什么它可以毫无问题地运行?@llxxee您正在声明两个不同的函数,它们的参数的
    常数不同。其中一个是类的朋友,没有定义,另一个有定义,但因为它的签名不同于朋友函数,所以它不会是类的朋友。编译器不会抱怨,因为第一个函数从不调用。如果您添加两个
    常量A
    ,您将得到
    未解决的外部
    链接器错误,或者如果您访问
    操作符+
    内部的
    A
    的私有成员变量,您将看到编译器抱怨
    无法访问
    的私有成员@llxxee抱歉我的英语不好。有时候我脑子里有一个句子,但我不能用英语很好地表达出来。你的解释对我来说很清楚:)顺便说一下,我发现如果我声明一个函数,比如
    void f(const int m)
    ,而不定义
    const
    like
    void f(int m){cout@llxxee您的示例只是一个特例。有关本例的更多信息,请参见此处:但您可以将参数更改为int&并使用
    const
    变量调用您的函数。(
    const int i=5;f(i);
    )您将看到您将得到
    未解析符号
    错误。
    template<>
    A<int> operator+(const A<int>&, const A<int>&)
    {
    }
    
    template<class T1>
    friend A<T1> operator+ (const A<T1>&, const A<T1>&);
    
    template<class T>
    A<T> operator + (const A<T>& , const A<T>&);