This is tricky, and it is covered by a C++ FAQ entry.
I can't explain exactly why your compiler gives the errors it does. But your code for all the operators is incorrect: as explained in the FAQ, the compiler thinks you are trying to friend
a non-template function, however this cannot work because the functions do need to be template functions in order to accept a Set<T>
.
The FAQ's suggested solution is to declare the template functions first , before you friend them:
template<typename T> class Set;
template<typename T>
Set<T> operator+ (const Set<T>& left, const Set<T>& right);
template<typename T>
Set<T> operator- (const Set<T>& left, const Set<T>& right);
template<typename T>
Set<T> operator/ (const Set<T>& left, const Set<T>& right);
template<class T>
class Set
{
friend Set<T> operator+ <> (const Set<T>& left, const Set<T>& right);
friend Set<T> operator- <> (const Set<T>& left, const Set<T>& right);
friend Set<T> operator/ <> (const Set<T>& left, const Set<T>& right);
Note that you need to be using Set<T>
, not just Set
as in your original code.
This works because now the compiler knows we are talking about function templates, so it recognizes them in the friend
line.
Another possible solution is this, without the forward-declarations of functions:
template<class T>
class Set
{
template<class U>
friend Set<U> operator / (const Set<U>& left, const Set<U>& right);
template<class U>
friend Set<U> operator+ (const Set<U>& left, const Set<U>& right);
template<class U>
friend Set<U> operator- (const Set<U>& left, const Set<U>& right);
public:
// ...
where you explicitly refer to template functions as friends. I'm not completely sure that this second approach is a good idea.
If your operators have "normal" semantics then perhaps you can avoid this issue together, but not using friend
s at all. If you define member functions operator+=
, operator-=
, operator/=
that operate on *this
, then it is simple to declare the other operators, outside of the class, that delegate to those functions without needing to be friends:
template<typename T>
Set<T> operator+ (Set<T> a, Set<T> const &b} { return a += b; }