0

So for class this week I have to use a set to read in the Declaration of Independence and the US Constitution from a .txt file, store them in sets, and overload operator* to find and return the intersection of the two sets.

Reading everything in is not a problem, neither is finding out the intersection in the sets. What I'm having a lot of trouble with is overloading operator*. I keep getting two errors:

no operator "*" matches these operands and

binary "*":'std::set<_Kty>' does not define this operator or a conversion to a type acceptable to the predefined operator

Here is my code so far:

From main:

Reader r;
std::set<std::string> d, c;
d = r.GetDeclaraton();
c = r.GetConstitution();
Set dec(d), con(c);
Set intersection = dec * con;

The errors are coming from that last line of main.

From Set.h

class Set
{   
public:
    std::set<std::string> s;
    Set(void);
    Set(std::set<std::string> set)
    {
        s = set;
    }
    ~Set(void);
    std::set<std::string> operator* (const std::set<std::string> &rhs)
    {
        std::set<std::string> newset;
        std::set<std::string>::iterator rhsiter = rhs.begin(), result;
        while (rhsiter != rhs.end())
        {
            result = s.find(*rhsiter++);
            if (result != rhs.end())
            {
                newset.insert(*result);
            }
        }
        return newset;
    }
};
3
  • @TonyD I edited it because I had been using it differently before I posted, but still no luck. Commented Mar 11, 2014 at 23:40
  • @user3280133 - you do know that there is a std::set_intersection function, right? cplusplus.com/reference/algorithm/set_intersection Your operator* can be written in 2 lines if you use the algorithm functions Commented Mar 11, 2014 at 23:41
  • usage - #include <iterator> set<std::string> newset;' 'set_intersection(s.begin(), s.end(), rhs.bgin(), rhs.end(), std::inserter(newset.begin())); return newset; So I was wrong -- not 2 lines, 1 line. Commented Mar 11, 2014 at 23:47

3 Answers 3

2

You need

Set operator* (const Set &rhs) const

because this is a binary operator with two Sets as arguments. Your attempt would only work if your Set was deriving std::set.

The return type here is Set. It makes more sense to be the same as the input arguments, and this is also consistent with your usage in main. So in this case you need to modify the definition to construct and return a Set instead of an std::set (or rather you need not because an std::set can be implicitly converted to a Set).

Note also I made operator* a const member function, since it's not modifying its object.

Sign up to request clarification or add additional context in comments.

6 Comments

Ok so I changed everything so that it makes logical sense like you corrected me on, but now I'm getting an unresolved external error from main. I #included Set.h <set> and Reader.h, what am I missing?
What's the name of the external?
@ivar unresolved external symbol "public: _thiscall Set::~Set(void): (??1Set@@QAE@XZ) referenced in function_wmain
That's because you declared ~Set(void); and did not define it anywhere. You don't need it, just remove it.
Also you can replace Set(void); with Set() = default;.
|
1

operator* is defined in your custom Set so the left-hand-side argument must be a Set, but in dec.s * con.s you're using .s which accesses the member std::set fields, and there's no operator* defined for a left-hand Set and rhs-hand std::set.

You could change to dec * con.s, but it'd be better to change the operator* rhs argument to a const Set& too, and use rhs.s inside the operator... less confusing!

Comments

1

In my opinion its better to write a global or friend operator. Also, for intersection I would use the & operator, for union the | or + operator while, difference: -...

Why global operators? With global operators you can write an operator for your class even if the left operand is not your class. For example in case of a matrix class you can easily write a global operator that multiplies together a float and a matrix while as a matrix member operator you could write only an operator where your matrix is on the left.

Example:

template <typename T>
inline std::set<T> intersection(const std::set<T>& smaller, const std::set<T>& larger)
{
    std::set<T> result;
    for (auto it=smaller.begin(),eit=smaller.end(); it!=eit; ++it)
    {
        if (larger.find(*it) != larger.end())
            result.insert(*it);
    }
    return result;
}

template <typename T>
inline std::set<T> operator & (const std::set<T>& a, const std::set<T>& b)
{
    if (a.size() < b.size())
        return intersection(a, b);
    return intersection(b, a);
}

class Set
{   
public:
    std::set<std::string> s;
    Set() {}
    Set(std::set<std::string> _s) : s(_s) {}

    friend Set operator & (const Set& a, const Set& b)
    {
        return Set(a.s & b.s);
    }
};

int test()
{
    std::set<std::string> s, t;
    s.insert("aa");
    s.insert("bb");
    t.insert("bb");
    t.insert("cc");
    std::set<std::string> u(s & t);

    Set ss(s), st(t);
    Set result(ss & st);
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.