简体   繁体   中英

set<> class, when I insert into the class, it doesn't accept my < operator

class Tuple
{
private:
    vector<string> values;
public:
    Tuple(vector<Parameter> newValues)
    {
        for(int i = 0; i < newValues.size(); i++)
        {
            string val = newValues[i].getValue();
            values.push_back(val);
        }
    }

    Tuple(vector<string> newAttributes)
    {
        values = newAttributes;
    }

    ~Tuple()
    {

    }

    bool operator < (Tuple &tup)
    {
        if(values < tup.getStringVec())
            return true;

        return false;
    }

    bool operator <= (Tuple &tup)
    {
        if(values <= tup.getStringVec())
            return true;

        return false;
    }

    bool operator > (Tuple &tup)
    {
        if(values > tup.getStringVec())
            return true;

        return false;
    }

    bool operator >= (Tuple &tup)
    {
        if(values >= tup.getStringVec())
            return true;

        return false;
    }
};


class Relation
{
private:

    set<Tuple> tupleSet;
public:
    Relation():
    {

    }

    ~Relation()
    {

    }

    void addToTupleSet(Tuple newTuple)
    {
        tupleSet.insert(newTuple); //<<this causes the problem
    }

};

Your predicate must provide operator like:

struct Compare
{
    bool operator() ( const T1& lhs, const T2& rhs )
    {
        // here's the comparison logic
        return bool_value;
    }
};

and specify it as the set's comparator:

std::set<Tuple, Compare> tupleSet;

The default comparator for std::set uses std::less<T> , which requires the object be exposed to an operator < of some form. This will be generally one of two forms:

A free function, like this:

bool operator <(const Tuple& arg1, const Tuple& arg2);

or a member function, like this:

class Tuple
{
public:
    bool operator <(const Tuple& arg) const
    {
        // comparison code goes here
    }
};

If you don't want to implement operator < just for use in a std::set you can certainly implement your own binary comparator type directly and use that as the comparator alternative to std::less<T> . Whether you do is your call, and a different solution to a different question (ie how to do that, which Niyaz covered in another answer).

Your code, slightly modified to not suck in namespace std and using references where appropriate (you may want to take a look at those, btw, as they will significantly reduce your time spent copying data to and fro).

#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <set>

// I added this, as your source included no such definition 
class Parameter
{
public:
    Parameter(const std::string s) : s(s) {}

    const std::string& getValue() const { return s; }

private:
    std::string s;
};

class Tuple
{
private:
    std::vector<std::string> values;

public:
    Tuple(const std::vector<Parameter>& newValues)
    {
        for(auto val : newValues)
            values.push_back(val.getValue());
    }

    Tuple(const std::vector<std::string>& newAttributes)
        : values(newAttributes)
    {
    }

    // note const member and parameter. neither the passed object nor
    //  this object should be modified during a comparison operation.
    bool operator < (const Tuple &tup) const
    {
        return values < tup.values;
    }
};


class Relation
{
private:
    std::set<Tuple> tupleSet;

public:
    void addToTupleSet(const Tuple& tup)
    {
        tupleSet.insert(tup);
    }
};

int main(int argc, char *argv[])
{
    Tuple tup({"a","b","c"});
    Relation rel;

    rel.addToTupleSet(tup);

    return 0;
}

Use below for operator "<"

bool operator < (const Tuple &tup) const
{
    /*if(values < tup.getStringVec())
        return true;*/             //getStringVec undefined, so comment out temporarily

    return false;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM