C++ Errors trying to overload the / operator in a templated class

Tag: c++ , operator-overloading , template-classes Author: JX0901QIN Date: 2014-04-23

I'm trying to overload the '+', '-', and '/' operators for a templated class i created. the + and - operators work perfectly, but the / operator overload is giving me errors.

I'm using Visual Studio 2013

//Set.h 
#pragma once
#include <iostream>
#include <vector>
using namespace std;

template<class T>
class Set
{   
    friend Set<T> operator+ <> (const Set& left, const Set& right);  //works
    friend Set<T> operator- <> (const Set& left, const Set& right);  //works
    friend Set<T> operator/ <> (const Set& left, const Set& right);  //does not

public:
    Set(int n)
    {
        numItems = n;
        setItems();
    }
    Set()
    {
        numItems = 0;
        setItems();
    }
    ~Set();
    void setItems();
    void output();
private:
    int numItems;
    vector<T> set;
};

I am wanting to overload the / operator to determine the intersection of two sets

Definition:

    //---------------- Overload intersection -----------------
template<class T>
Set<T> operator/(const Set<T>& left, const Set<T>& right)
{
    bool putin = false;
    Set<T> quotient;

    // loops through left Set
    for (int i = 0; i < left.set.size(); i++)
    {
        for (int j = 0; j < right.set.size(); j++)
            //loops through right set
        {
            //checks if the item in left is in right set
            // if it is, PUT IT IN the new set
            if (left.set[i] == right.set[j])
                putin = true;
        }
        if (putin)
            quotient.set.push_back(left.set[i]);
        putin = true;
    }

    return quotient;
} 

Here are the errors i'm getting

Error 1 error C2143: syntax error : missing ';' before '<'

Error 2 error C2460: '/' : uses 'Set<T>', which is being defined

Error 3 error C2433: '/' : 'friend' not permitted on data declarations

Error 4 error C2238: unexpected token(s) preceding ';'

Error 5 error C2365: '/' : redefinition; previous definition was 'data variable'

Error 6 error C2904: '/' : name already used for a template in the current scope

Error 7 error C2460: '/' : uses 'Set<int>', which is being defined

Best Answer

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 friends 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; }