Hello all,
I came across quite unpleasant problem.
Little intro: I created templated Multiset class, suitable for use in Coloured Petri Nets, nothing fancy. As a private data holder, I'm using the QHash class.
Let's have a look on the header:
template<class T>
class Multiset
{
typedef class QHash<T, uint>::iterator Iterator;
typedef class QHash<T, uint>::const_iterator ConstIterator;
public:
Multiset();
virtual ~Multiset();
...
Multiset<T> operator-(const Multiset<T>& other) const;
Multiset<T> operator*(uint scalar) const;
bool operator<=(const Multiset<T>& other) const;
private:
QHash<T, uint> m_values;
};
template<class T>
class Multiset
{
typedef class QHash<T, uint>::iterator Iterator;
typedef class QHash<T, uint>::const_iterator ConstIterator;
public:
Multiset();
virtual ~Multiset();
...
Multiset<T> operator-(const Multiset<T>& other) const;
Multiset<T> operator*(uint scalar) const;
bool operator<=(const Multiset<T>& other) const;
private:
QHash<T, uint> m_values;
};
To copy to clipboard, switch view to plain text mode
I took the liberty to post only the relevant part.
Now the method definitions (methods, which doesn't behave correctly):
template<class T>
Multiset<T> Multiset<T>::operator-(const Multiset<T>& other) const
{
Multiset<T> ret = *this;
ConstIterator itOther = other.m_values.constBegin();
if (!(ret <= other))
{
while (itOther != other.m_values.constEnd())
{
ret.m_values[itOther.key()] -= itOther.value();
++itOther;
}
}
return ret;
}
...
template<class T>
bool Multiset<T>::operator<=(const Multiset<T>& other) const
{
bool ret = false;
ConstIterator itThis;
ConstIterator itOther = other.m_values.constBegin();
while (itOther != other.m_values.constEnd())
{
itThis = m_values.find(itOther.key());
if (itThis == m_values.constEnd()
|| itThis.value() <= itOther.value())
{
ret = true;
break;
}
++itOther;
}
return ret;
}
template<class T>
Multiset<T> Multiset<T>::operator-(const Multiset<T>& other) const
{
Multiset<T> ret = *this;
ConstIterator itOther = other.m_values.constBegin();
if (!(ret <= other))
{
while (itOther != other.m_values.constEnd())
{
ret.m_values[itOther.key()] -= itOther.value();
++itOther;
}
}
return ret;
}
...
template<class T>
bool Multiset<T>::operator<=(const Multiset<T>& other) const
{
bool ret = false;
ConstIterator itThis;
ConstIterator itOther = other.m_values.constBegin();
while (itOther != other.m_values.constEnd())
{
itThis = m_values.find(itOther.key());
if (itThis == m_values.constEnd()
|| itThis.value() <= itOther.value())
{
ret = true;
break;
}
++itOther;
}
return ret;
}
To copy to clipboard, switch view to plain text mode
My problem is, that no matter what the lessOrEqual operator returns, it always jumps inside the:
if (!(ret <= other))
{
while (itOther != other.m_values.constEnd())
{
ret.m_values[itOther.key()] -= itOther.value();
++itOther;
}
}
if (!(ret <= other))
{
while (itOther != other.m_values.constEnd())
{
ret.m_values[itOther.key()] -= itOther.value();
++itOther;
}
}
To copy to clipboard, switch view to plain text mode
And it is causing the first series of QCOMPARE to fail in this testcase:
void Multiset_mt::operatorMinus()
{
QFETCH(uint, value);
QFETCH(uint, result);
QCOMPARE(value, result);
}
void Multiset_mt::operatorMinus_data()
{
const uint first_color_size = 2;
const uint second_color_size = 1;
const uint third_color_size = 0;
const uint not_valid_sub_size = 0;
Multiset<Color> ms1, ms2, msRes;
Color c1("black"), c2("red"), c3("blue");
ms1.insert(c1);
ms1.insert(c2);
ms1.insert(c2);
ms2.insert(c1);
ms2.insert(c2);
ms2.insert(c3);
msRes = ms1 - ms2;
QTest::addColumn<uint>("value");
QTest::addColumn<uint>("result");
QTest::newRow("NOT VALID Size == 0") << msRes.size(c1) << not_valid_sub_size;
QTest::newRow("NOT VALID Size == 0") << msRes.size(c2) << not_valid_sub_size;
QTest::newRow("NOT VALID Size == 0") << msRes.size(c3) << not_valid_sub_size;
ms1.insert(c1);
ms1.insert(c1);
ms2.remove(c3);
msRes = ms1 - ms2;
QTest::newRow("Size == 2") << msRes.size(c1) << first_color_size;
QTest::newRow("Size == 1") << msRes.size(c2) << second_color_size;
QTest::newRow("Size == 0") << msRes.size(c3) << third_color_size;
}
void Multiset_mt::operatorMinus()
{
QFETCH(uint, value);
QFETCH(uint, result);
QCOMPARE(value, result);
}
void Multiset_mt::operatorMinus_data()
{
const uint first_color_size = 2;
const uint second_color_size = 1;
const uint third_color_size = 0;
const uint not_valid_sub_size = 0;
Multiset<Color> ms1, ms2, msRes;
Color c1("black"), c2("red"), c3("blue");
ms1.insert(c1);
ms1.insert(c2);
ms1.insert(c2);
ms2.insert(c1);
ms2.insert(c2);
ms2.insert(c3);
msRes = ms1 - ms2;
QTest::addColumn<uint>("value");
QTest::addColumn<uint>("result");
QTest::newRow("NOT VALID Size == 0") << msRes.size(c1) << not_valid_sub_size;
QTest::newRow("NOT VALID Size == 0") << msRes.size(c2) << not_valid_sub_size;
QTest::newRow("NOT VALID Size == 0") << msRes.size(c3) << not_valid_sub_size;
ms1.insert(c1);
ms1.insert(c1);
ms2.remove(c3);
msRes = ms1 - ms2;
QTest::newRow("Size == 2") << msRes.size(c1) << first_color_size;
QTest::newRow("Size == 1") << msRes.size(c2) << second_color_size;
QTest::newRow("Size == 0") << msRes.size(c3) << third_color_size;
}
To copy to clipboard, switch view to plain text mode
If anyone could help me with this, it would be really appreciated. Maybe I missed something. Thank you.
I tried to also attach the whole files.
Bookmarks