1

I have this code for the class IdTask

class IdTask
{
public:
IdTask(QString host, QString id) : _host(host), _id(id) {}
IdTask(const IdTask & idT) : _host(idT._host), _id(idT._id) {}

QString host() const { return _host;}
QString id() const { return _id;}

inline bool operator ==(const IdTask& idT) const { return _host == idT.host() && _id == idT.id();}
inline bool operator <(const IdTask& idT) const { return _host < idT.host() && _id < idT.id();}

private:
QString _host;
QString _id;
};

And the class IdResult

class IdResult
{
public:
IdResult(IdTask idT, QString id) : _idTask(idT), _id(id) {}
IdTask idTask() const { return _idTask;}
QString id() const { return _id;}
bool operator < (const IdResult& idR) const { return _idTask < idR.idTask() && _id < idR.id();}
private:
IdTask _idTask;
QString _id;
};

I create a QMap like this :

QMap<IdResult, QString> mapIdResultInput;
mapIdResultInput.insert(IdResult(IdTask("localhost", "init"), "a"), "_a");

The problem is with the function contains.

mapIdResultInput.contains(IdResult(IdTask("b", "c"), "g"));

It return always true. What is the problem with my code?

artoon
  • 729
  • 2
  • 14
  • 41
  • 1
    If `QMap` is anything like `std::map` (and the docs say it is a red-black tree), then it would need a *strict weak ordering* for the keys, presumably taken from `operator<`. Yours isn't a strict weak ordering. You need to fix that for the map to work. – juanchopanza Aug 07 '14 at 06:35
  • Why my `operator<` isn't a strict weak ordering? – artoon Aug 07 '14 at 06:41
  • For example, both `{99, 2} < {100, 1}` and `{100, 1} < {99, 2}` are false. That makes both equivalent in your ordering. – juanchopanza Aug 07 '14 at 06:46
  • Ok! So the solution is compute a hash of IdResult and compare this hash? – artoon Aug 07 '14 at 06:51
  • 2
    I doubt it. If you need an ordering, a hash won't do. You can implement a lexicographical comparison based on host and id, but you have to make sure that if the first host is < the second one, you immediately return true, you don't even consider the id. You only consider the id when the hosts are equal. – juanchopanza Aug 07 '14 at 06:57
  • 1
    See [this related question](http://stackoverflow.com/questions/979759/operator-and-strict-weak-ordering), also look at [`std::tie`](http://en.cppreference.com/w/cpp/utility/tuple/tie). – juanchopanza Aug 07 '14 at 06:58

1 Answers1

1

I would solve this in the following way: I would sort my IdResults first by IdTask and than, if IdTasks are equal, by id. Here is my implementation of your operators in the classes:

class IdTask
{
public:
    [..]
    bool operator ==(const IdTask& idT) const
    { return _host == idT.host() && _id == idT.id(); }

    bool operator <(const IdTask& idT) const 
    { return (_host < idT.host()) || (_host == idT.host() && _id < idT.id()); }
    [..]
};

And

class IdResult
{
    [..]
    bool operator < (const IdResult& idR) const 
    { return (_idTask < idR.idTask()) || (_idTask == idR.idTask() && _id < idR.id()); }
    [..]
};

And the test

QMap<IdResult, QString> mapIdResultInput;
mapIdResultInput.insert(IdResult(IdTask("localhost", "init"), "a"), "_a");

bool b = mapIdResultInput.contains(IdResult(IdTask("b", "c"), "g")); // false
b = mapIdResultInput.contains(IdResult(IdTask("localhost", "init"), "a")); // true
vahancho
  • 20,808
  • 3
  • 47
  • 55