模板运算符似乎因歧义而失败

template operators fail seemingly on ambiguity

这不是重复的。我检查了很多答案、常见问题解答和其他内容。这些都没有告诉我消息。这是简化的代码。这是获得并解释错误的最低要求。

/*** Polynomial.hpp ********************************************************/

namespace Modulus
{
// Forward declaration of the types and non-inline template friend functions.

template <typename T>
    class Polynomial;

template <typename T>
    Polynomial<T>  operator +
        (Polynomial<T> const & p,
         Polynomial<T> const & q);
}

namespace Modulus
{

template <typename T>
class Polynomial
{
public:
    Polynomial() { }

    // [!] when you comment this in, you get the error.
    //Polynomial      operator +      () const { return *this; }

    friend Polynomial operator + <> (Polynomial const & p,
                                     Polynomial const & q);
};

} // namespace

// Template: include .cpp file.
   //#include "Polynomial.cpp"
///^ It is commented out, for compiling in one file.


/*** Polynomial.cpp ********************************************************/

namespace Modulus
{

template <typename T>
Polynomial<T>
    operator + (Polynomial<T> const & p,
                Polynomial<T> const & q)
{
    return Polynomial<T>();
}

} // namespace


/*** main.cpp **************************************************************/


//#include "Polynomial.hpp"

using namespace Modulus;

int main()
{
    Polynomial<int> p;
    p + p;
    return 0;
}

当我在 [!] 下注释行时,我得到的错误是 friends can only be classes or functions (Clang++) 或 declaration of ‘operator+’ as non-function (g++)。

对我来说,编译器似乎弄错了这两个运算符。据我了解的运算符重载知识,一元运算符和二元运算符是完全独立的,可以通过参数数量.

进行唯一区分

那么为什么会出现这个错误呢?使用标准实践使一元运算符成为朋友,使代码在两个编译器上都能正常编译。

当您在范围内声明某些内容时,它会隐藏任何更大范围内的同名声明。这里,成员 operator+ 的声明隐藏了非成员的声明。所以 friend 声明指的是成员,而不是非成员,因此是错误的。

如果要在同一范围内引用两者,则需要限定名称:

Polynomial      operator +      () const { return *this; }

friend Polynomial Modulus::operator + <> (Polynomial const & p, Polynomial const & q);
                  ^^^^^^^^^