Does anybody know why this compiles:
template<typename T>
class Foo;
template<typename T>
bool operator==(const T& l, const Foo<T>& r);
template<typename T>
class Foo
{
public:
Foo();
~Foo();
friend bool operator== <> (const T& l, const Foo<T>& r);
bool operator==(const Foo<T>& r);
};
But this does not (only difference is order of member vs friend operator==):
template<typename T>
class Foo;
template<typename T>
bool operator==(const T& l, const Foo<T>& r);
template<typename T>
class Foo
{
public:
Foo();
~Foo();
bool operator==(const Foo<T>& r);
friend bool operator== <> (const T& l, const Foo<T>& r);
};
I was banging my head against the second case, with an "error: declaration of ‘operator==’ as non-function" at the friend line. I finally decided there must be something wrong before the friend declaration, so I tried moving it up in the code to see if I could get a different error. Lo and behold, when I moved it above the member declaration, everything worked!
It's because after declaring a member
operator==in the scope of the class, the nameoperator==will refer to that instead of the global template.I'm not sure that's the correct behaviour (might be a compiler bug, may also fall foul of https://stackoverflow.com/a/15538759/5754656), but what's happening is that
operator==is parsed as a non-template, so the next<is a less than sign rather than part of a template-id.Qualifying it so that the non-member
operator==is found instead fixes this: