简体   繁体   中英

How to define a friend operator declared on a template in a namespace?

I have a class like this:

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

And I've been trying to define that operator + separately, but I can't get it to work.

I've tried:

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

But I get "C2244 'operator +': unable to match function definition to an existing declaration"

I've tried:

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

But I get a linker error.

I've tried:

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

But I get the same linker error.

I can't figure out what the issue is or how to resolve it. The operator has to be a friend because it's accessing a private field (I'd have to make the field public otherwise, which I don't want to do if I can avoid it).

operator+ is declared as a non-template function inside the class definition, but you're trying to define it as a function template later, they don't match. If you want to make it a function template, you can

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

If you want to make it a non-template function, then just define it inside the class definition:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM