C++ 如何定义在命名空间中的模板上声明的友元运算符?

C++ 如何定义在命名空间中的模板上声明的友元运算符?,c++,templates,friend,C++,Templates,Friend,我有一门课是这样的: namespace N { template<unsigned Mantissa, unsigned Fraction> class C { //... public: friend C<Mantissa, Fraction> operator +(const C<Mantissa, Fraction> & left, const C<Mantissa, Fraction> & ri

我有一门课是这样的:

namespace N
{
  template<unsigned Mantissa, unsigned Fraction>
  class C
  {
  //...
  public:
    friend C<Mantissa, Fraction> operator +(const C<Mantissa, Fraction> & left, const C<Mantissa, Fraction> & right);
  //...
  };
}
但我得到“C2244‘运算符+”:无法将函数定义与现有声明匹配”

我试过:

    template<unsigned Mantissa, unsigned Fraction>
    N::C<Mantissa, Fraction> N::operator+(const N::C<Mantissa, Fraction> & left, const N::C<Mantissa, Fraction> & right)
    {
        //...
    }
    template<unsigned Mantissa, unsigned Fraction>
    N::C<Mantissa, Fraction> operator+(const N::C<Mantissa, Fraction> & left, const N::C<Mantissa, Fraction> & right)
    {
        //...
    }
namespace N
{
    template<unsigned Mantissa, unsigned Fraction>
    C<Mantissa, Fraction> operator+(const C<Mantissa, Fraction> & left, const C<Mantissa, Fraction> & right)
    {
        //...
    }
}
模板
N::C运算符+(常数N::C和左、常数N::C和右)
{
//...
}
但我得到一个链接器错误

我试过:

    template<unsigned Mantissa, unsigned Fraction>
    N::C<Mantissa, Fraction> N::operator+(const N::C<Mantissa, Fraction> & left, const N::C<Mantissa, Fraction> & right)
    {
        //...
    }
    template<unsigned Mantissa, unsigned Fraction>
    N::C<Mantissa, Fraction> operator+(const N::C<Mantissa, Fraction> & left, const N::C<Mantissa, Fraction> & right)
    {
        //...
    }
namespace N
{
    template<unsigned Mantissa, unsigned Fraction>
    C<Mantissa, Fraction> operator+(const C<Mantissa, Fraction> & left, const C<Mantissa, Fraction> & right)
    {
        //...
    }
}
名称空间N
{
模板
C运算符+(常数C和左、常数C和右)
{
//...
}
}
但我得到了相同的链接器错误

我不知道问题是什么,也不知道如何解决。
操作符
必须是
朋友
,因为它正在访问一个
私有
字段(我必须将该字段
公开
,否则,如果可以避免的话,我不想这样做)。

操作符+
在类定义中声明为非模板函数,但您稍后试图将其定义为函数模板,它们不匹配。如果您想使其成为函数模板,可以

namespace N
{
  // forward declaration of the class template
  template<unsigned Mantissa, unsigned Fraction>
  class C;
  // forward declaration of the function template
  template<unsigned Mantissa, unsigned Fraction>
  C<Mantissa, Fraction> operator +(const C<Mantissa, Fraction> & left, const C<Mantissa, Fraction> & right);

  template<unsigned Mantissa, unsigned Fraction>
  class C
  {
  //...
  public:
    // the instantiation of operator+ with template parameter of current Mantissa and Fraction becomes friend
    friend C<Mantissa, Fraction> operator + <>(const C<Mantissa, Fraction> & left, const C<Mantissa, Fraction> & right);
    //                                      ~~
  //...
  };
}

// definition of the function template
template<unsigned Mantissa, unsigned Fraction>
N::C<Mantissa, Fraction> N::operator+(const N::C<Mantissa, Fraction> & left, const N::C<Mantissa, Fraction> & right)
{
    //...
}
名称空间N
{
//类模板的转发声明
模板
丙级;;
//函数模板的前向声明
模板
C运算符+(常数C和左、常数C和右);
模板
C类
{
//...
公众:
//模板参数为当前尾数和分数的运算符+的实例化成为朋友
友元C运算符+(常数C和左、常数C和右);
//                                      ~~
//...
};
}
//函数模板的定义
模板
N::cn::operator+(常数N::C和left,常数N::C和right)
{
//...
}
如果要使其成为非模板函数,则只需在类定义中定义它:

namespace N
{
  template<unsigned Mantissa, unsigned Fraction>
  class C
  {
  //...
  public:
    // defined as non-template
    friend C<Mantissa, Fraction> operator +(const C<Mantissa, Fraction> & left, const C<Mantissa, Fraction> & right) {
      //...
    }
  //...
  };
}
名称空间N
{
模板
C类
{
//...
公众:
//定义为非模板
友元C运算符+(常数C和左、常数C和右){
//...
}
//...
};
}

为什么在
N::C
中使用
T
???你的模板是
template
@NathanOliver我在打问题时犯了一个小错误。它实际上在实际代码中使用了
,现在将问题调整为匹配。是否必须在类定义中定义非模板运算符?(到目前为止,我只是在类定义中声明函数并在以后定义它们。)@Pharap我假设您可以像处理模板类的任何其他成员函数一样处理
template N::C N::C::operator+…
。@cdhowie将其作为成员函数的问题是,我必须处理操作符的问题。@Pharap顺便说一下,在
C
的定义中,
C
成为特定实例化的别名。So
friend C操作符+(常数C&左,常数C&右)可以简化为
友元C操作符+(常数C和左、常数C和右)
.AFAIK不可能在使用class template参数的主体之外以任何方式定义模板类的友元函数。这只是一个奇怪的边缘案例,允许朋友函数与成员函数一起实例化,但我知道没有语法可以让您在主体之外定义它。如果有人认为这是可能的,我希望看到一个反例。