I have a template class, to which I declared 2 operator+
methods. Their declaration is:
1) const MyClass<T> operator+ (int num) const;
and
2) friend const MyClass<T> operator+ <>(int num, const MyClass<T>& other);
Following this FAQ, the .hpp file looks something like this:
//forward declaration of the class.
template<class T>
class MyClass;
//forward declaration of the operator+
template<class T>
const MyClass<T> operator+ (int num, const MyClass<T>& other);
template<class T>
class MyClass {
public:
...
const MyClass<T> operator+ (int num) const;
friend const MyClass<T> operator+ <>(int num, const MyClass<T>& other);
...
};
(And later I have the definitions of those methods).
Note that the 2 operator+
methods are used in different situations:
The first in
MyClass mc;
mc+5;
And the second in
MyClass mc;
5+mc;
But for some reason, when I compile it in g++ (version 4.8.2, if that matters), I get the error:
declaration of ‘operator+’ as non-function
friend const MyClass<T> operator+ <>(int num, const MyClass<T>& other);
Note that the error refers to the friend
operator+
method
But, if I remove the declaration of the first operator+
method (i.e. leaving only the friend
one), then everything compiles just fine!
What is going on?
Not sure why, but switching the order makes it compile (will try to find an explaination):
//forward declaration of the class.
template<class T>
class MyClass;
//forward declaration of the operator+
template<class T>
const MyClass<T> operator+(int num, const MyClass<T>& other);
template<class T>
class MyClass {
public:
friend const MyClass<T> operator+<>(int num, const MyClass<T>& other);
const MyClass<T> operator+ (int num) const;
};
EDIT
Thanks to Maksim for pointing out that my doubts were true. What happens is that the names of both operators clash and thus the error. Normally the second operator would have the class name in it's name, but since in the class declaration you are inside class scope the names clash. If the non class member operator would be in a different namespace, e.g:
//forward declaration of the class.
template<class T>
class MyClass;
//forward declaration of the operator+
namespace Foo
{
template<class T>
const MyClass<T> operator+(int num, const MyClass<T>& other);
}
template<class T>
class MyClass {
public:
const MyClass<T> operator+ (int num) const;
friend const MyClass<T> Foo::operator+<>(int num, const MyClass<T>& other);
};
using namespace Foo;
int main()
{
MyClass<int> a;
5 + a;
}
it would be fine since the names would be distinct. Also if you would use them as friends on another object it would also be fine:
//forward declaration of the class.
template<class T>
class MyClass;
//forward declaration of the operator+
template<class T>
const MyClass<T> operator+(int num, const MyClass<T>& other);
template<class T>
class MyClass {
public:
const MyClass<T> operator+ (int num) const;
};
template <typename T>
class Foo
{
friend const MyClass<T> operator+<>(int num, const MyClass<T>& other);
friend const MyClass<T> MyClass<T>::operator+(int num);
};
int main()
{
MyClass<int> a;
5 + a;
}
I hope this explains these examples explain the cause.