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

时间:2017-05-01 13:37:07

标签: 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> & right);
  //...
  };
}

我一直试图单独定义operator +,但我无法让它发挥作用。

我试过了:

    template<unsigned Mantissa, unsigned Fraction>
    N::C<Mantissa, Fraction> N::operator+(const N::C<Mantissa, Fraction> & left, const N::C<Mantissa, Fraction> & right)
    {
        //...
    }

但我得到“C2244'运算符+':无法将函数定义与现有声明匹配”

我试过了:

    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)
    {
        //...
    }
}

但是我得到了相同的链接器错误。

我无法弄清楚问题是什么或如何解决它。 operator必须是friend,因为它正在访问private字段(否则我必须创建字段public,我不想这样做我可以避免它。)

1 个答案:

答案 0 :(得分:3)

operator+被声明为类定义中的非模板函数,但您稍后尝试将其定义为函数模板,它们不匹配。如果你想把它变成一个功能模板,你可以

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)
{
    //...
}

如果你想让它成为一个非模板函数,那么只需在类定义中定义它:

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) {
      //...
    }
  //...
  };
}