Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

template operators fail seemingly on ambiguity

This is not a duplicate. I've checked lots of answers, the FAQ and else. Nothing of that told me news. Here is the simplified code. It's the minimum to get and explain the error.

/*** 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;
}

When I comment the line under [!] in, the error I get is friends can only be classes or functions (Clang++) or declaration of ‘operator+’ as non-function (g++).

For me, it seems the compilers mistake the two operators. As far as I've learned the operator overloading stuff, the unary and binary operators are completely independent and can be uniquely distinguished by their number of arguments.

So why does the error occur? Making the unary operator a friend using the standard practice, makes the code compile fine on both compilers.

like image 208
Bolpat Avatar asked Mar 28 '15 14:03

Bolpat


1 Answers

When you declare something in a scope, it hides delcarations of the same name in any wider scope. Here, the declaration of the member operator+ hides that of the non-member. So the friend declaration refers to the member, not the non-member, hence the error.

You'll need to qualify the name if you want to refer to both in the same scope:

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

friend Polynomial Modulus::operator + <> (Polynomial const & p, Polynomial const & q);
                  ^^^^^^^^^
like image 133
Mike Seymour Avatar answered Oct 08 '22 16:10

Mike Seymour