mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-17 10:55:32 +08:00
refs #413 Decomposed hash-related functions of CValueObject into Mixin::HashByTuple.
This commit is contained in:
@@ -118,8 +118,8 @@ namespace BlackMisc
|
|||||||
//! \copydoc CValueObject::convertFromQVariant
|
//! \copydoc CValueObject::convertFromQVariant
|
||||||
virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant< C<T> >(&derived(), variant); }
|
virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant< C<T> >(&derived(), variant); }
|
||||||
|
|
||||||
//! \copydoc BlackMisc::CValueObject::getValueHash
|
//! Simplifies composition, returns 0 for performance
|
||||||
virtual uint getValueHash() const override { return qHash(&derived()); }
|
friend uint qHash(const C<T> &) { return 0; }
|
||||||
|
|
||||||
//! \copydoc CValueObject::toJson
|
//! \copydoc CValueObject::toJson
|
||||||
virtual QJsonObject toJson() const override
|
virtual QJsonObject toJson() const override
|
||||||
|
|||||||
@@ -232,9 +232,6 @@ namespace BlackMisc
|
|||||||
//! \copydoc CValueObject::convertFromQVariant
|
//! \copydoc CValueObject::convertFromQVariant
|
||||||
virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant(this, variant); }
|
virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant(this, variant); }
|
||||||
|
|
||||||
//! \copydoc BlackMisc::CValueObject::getValueHash
|
|
||||||
virtual uint getValueHash() const override { return qHash(this); }
|
|
||||||
|
|
||||||
//! \copydoc CValueObject::toJson
|
//! \copydoc CValueObject::toJson
|
||||||
virtual QJsonObject toJson() const override
|
virtual QJsonObject toJson() const override
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -122,6 +122,10 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(BlackMisc::CLogPattern)
|
Q_DECLARE_METATYPE(BlackMisc::CLogPattern)
|
||||||
BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::CLogPattern, (o.m_severities, o.m_strategy, o.m_strings))
|
BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::CLogPattern, (
|
||||||
|
attr(o.m_severities, flags<DisabledForHashing>()),
|
||||||
|
attr(o.m_strategy),
|
||||||
|
attr(o.m_strings, flags<DisabledForHashing>())
|
||||||
|
))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -279,10 +279,10 @@ namespace BlackMisc
|
|||||||
//! Unequal operator !=
|
//! Unequal operator !=
|
||||||
bool operator != (const CMeasurementUnit &other) const;
|
bool operator != (const CMeasurementUnit &other) const;
|
||||||
|
|
||||||
//! \copydoc CValueObject::getValueHash
|
//! \copydoc CValueObject::qHash
|
||||||
virtual uint getValueHash() const override
|
friend uint qHash(const CMeasurementUnit &unit)
|
||||||
{
|
{
|
||||||
return qHash(this->getName());
|
return ::qHash(unit.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Name such as "meter"
|
//! Name such as "meter"
|
||||||
|
|||||||
@@ -198,8 +198,11 @@ namespace BlackMisc
|
|||||||
//! \copydoc CValueObject::unmarshallFromDbus
|
//! \copydoc CValueObject::unmarshallFromDbus
|
||||||
virtual void unmarshallFromDbus(const QDBusArgument &argument) override;
|
virtual void unmarshallFromDbus(const QDBusArgument &argument) override;
|
||||||
|
|
||||||
//! \copydoc CValueObject::getValueHash
|
//! \copydoc CValueObject::qHash
|
||||||
virtual uint getValueHash() const override;
|
uint getValueHash() const;
|
||||||
|
|
||||||
|
//! \copydoc CValueObject::qHash
|
||||||
|
friend uint qHash(const PQ &pq) { return pq.getValueHash(); };
|
||||||
|
|
||||||
//! \copydoc CValueObject::toJson
|
//! \copydoc CValueObject::toJson
|
||||||
virtual QJsonObject toJson() const override;
|
virtual QJsonObject toJson() const override;
|
||||||
|
|||||||
@@ -137,8 +137,11 @@ namespace BlackMisc
|
|||||||
//! Map
|
//! Map
|
||||||
const QMap<CPropertyIndex, CVariant> &map() const { return this->m_values; }
|
const QMap<CPropertyIndex, CVariant> &map() const { return this->m_values; }
|
||||||
|
|
||||||
//! \copydoc CValueObject::getValueHash
|
//! Hash value
|
||||||
virtual uint getValueHash() const override;
|
uint getValueHash() const;
|
||||||
|
|
||||||
|
//! \copydoc CValueObject::qHash
|
||||||
|
friend uint qHash(const CPropertyIndexVariantMap &vm) { return vm.getValueHash(); }
|
||||||
|
|
||||||
//! \copydoc CValueObject::toQVariant
|
//! \copydoc CValueObject::toQVariant
|
||||||
virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); }
|
virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); }
|
||||||
|
|||||||
@@ -110,9 +110,6 @@ namespace BlackMisc
|
|||||||
*/
|
*/
|
||||||
struct CValueObjectDummyBase
|
struct CValueObjectDummyBase
|
||||||
{
|
{
|
||||||
//! Value hash
|
|
||||||
static uint getValueHash() { return 0; }
|
|
||||||
|
|
||||||
//! To JSON
|
//! To JSON
|
||||||
static QJsonObject toJson() { return {}; }
|
static QJsonObject toJson() { return {}; }
|
||||||
|
|
||||||
@@ -240,6 +237,36 @@ namespace BlackMisc
|
|||||||
static bool baseIsA(const CEmpty *, int) { return false; }
|
static bool baseIsA(const CEmpty *, int) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* CRTP class template from which a derived class can inherit common methods dealing with hashing instances by metatuple.
|
||||||
|
*/
|
||||||
|
template <class Derived, bool IsTupleBased = true>
|
||||||
|
class HashByTuple : private Private::EncapsulationBreaker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! qHash overload, needed for storing value in a QSet.
|
||||||
|
friend uint qHash(const Derived &value, uint seed = 0)
|
||||||
|
{
|
||||||
|
return ::qHash(hashImpl(value), seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static uint hashImpl(const Derived &value)
|
||||||
|
{
|
||||||
|
return BlackMisc::qHash(toMetaTuple(value)) ^ baseHash(static_cast<const typename Derived::base_type &>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> static uint baseHash(const T &base) { return qHash(base); }
|
||||||
|
static uint baseHash(const CEmpty &) { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Specialization of HashByTuple for classes not registered with the tuple system.
|
||||||
|
*/
|
||||||
|
template <class Derived>
|
||||||
|
class HashByTuple<Derived, false>
|
||||||
|
{};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -255,13 +282,13 @@ namespace BlackMisc
|
|||||||
template <class Derived, class Base /*= CEmpty*/> class CValueObject :
|
template <class Derived, class Base /*= CEmpty*/> class CValueObject :
|
||||||
public Base,
|
public Base,
|
||||||
public Mixin::MetaType<Derived>,
|
public Mixin::MetaType<Derived>,
|
||||||
|
public Mixin::HashByTuple<Derived, Policy::Hash::IsMetaTuple<Derived, Base>::value>,
|
||||||
private CValueObjectPolicy<Derived>::Equals::template Ops<Derived, Base>,
|
private CValueObjectPolicy<Derived>::Equals::template Ops<Derived, Base>,
|
||||||
private CValueObjectPolicy<Derived>::LessThan::template Ops<Derived, Base>,
|
private CValueObjectPolicy<Derived>::LessThan::template Ops<Derived, Base>,
|
||||||
private CValueObjectPolicy<Derived>::Compare::template Ops<Derived, Base>
|
private CValueObjectPolicy<Derived>::Compare::template Ops<Derived, Base>
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<CEmpty, Base>::value || IsValueObject<Base>::value, "Base must be either CEmpty or derived from CValueObject");
|
static_assert(std::is_same<CEmpty, Base>::value || IsValueObject<Base>::value, "Base must be either CEmpty or derived from CValueObject");
|
||||||
|
|
||||||
using HashPolicy = typename CValueObjectPolicy<Derived>::Hash;
|
|
||||||
using DBusPolicy = typename CValueObjectPolicy<Derived>::DBus;
|
using DBusPolicy = typename CValueObjectPolicy<Derived>::DBus;
|
||||||
using JsonPolicy = typename CValueObjectPolicy<Derived>::Json;
|
using JsonPolicy = typename CValueObjectPolicy<Derived>::Json;
|
||||||
using PropertyIndexPolicy = typename CValueObjectPolicy<Derived>::PropertyIndex;
|
using PropertyIndexPolicy = typename CValueObjectPolicy<Derived>::PropertyIndex;
|
||||||
@@ -356,12 +383,6 @@ namespace BlackMisc
|
|||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! qHash overload, needed for storing value in a QSet.
|
|
||||||
friend uint qHash(const Derived &value, uint seed = 0)
|
|
||||||
{
|
|
||||||
return qHash(value.getValueHash(), seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//! Base class
|
//! Base class
|
||||||
using base_type = Base;
|
using base_type = Base;
|
||||||
@@ -396,12 +417,6 @@ namespace BlackMisc
|
|||||||
//! \copydoc BlackMisc::Mixin::MetaType::convertFromCVariant
|
//! \copydoc BlackMisc::Mixin::MetaType::convertFromCVariant
|
||||||
using Mixin::MetaType<Derived>::convertFromCVariant;
|
using Mixin::MetaType<Derived>::convertFromCVariant;
|
||||||
|
|
||||||
//! Value hash, allows comparisons between QVariants
|
|
||||||
virtual uint getValueHash() const
|
|
||||||
{
|
|
||||||
return HashPolicy::hashImpl(*derived()) ^ BaseOrDummy::getValueHash();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Cast to JSON object
|
//! Cast to JSON object
|
||||||
virtual QJsonObject toJson() const
|
virtual QJsonObject toJson() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -283,6 +283,11 @@ namespace BlackMisc
|
|||||||
template <class T, class...>
|
template <class T, class...>
|
||||||
static uint hashImpl(const T &) { return 0; }
|
static uint hashImpl(const T &) { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \private Detect the policy of T, following inheritance.
|
||||||
|
template <class T, class B, class P = typename CValueObjectPolicy<T>::Hash> struct IsMetaTuple : public std::false_type {};
|
||||||
|
template <class T, class B> struct IsMetaTuple<T, B, MetaTuple> : public std::true_type {};
|
||||||
|
template <class T, class B> struct IsMetaTuple<T, B, Inherit> : public IsMetaTuple<B, typename B::base_type> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace DBus
|
namespace DBus
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ namespace BlackMisc
|
|||||||
virtual bool equalsPropertyByIndex(const void *object, const CVariant &compareValue, const CPropertyIndex &index) const = 0;
|
virtual bool equalsPropertyByIndex(const void *object, const CVariant &compareValue, const CPropertyIndex &index) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \private Fallback in case qHash is not defined for T.
|
||||||
|
template <typename T>
|
||||||
|
uint qHash(const T &) { return 0; }
|
||||||
|
|
||||||
//! \private Implementation of IValueObjectMetaInfo representing the set of operations supported by T.
|
//! \private Implementation of IValueObjectMetaInfo representing the set of operations supported by T.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct CValueObjectMetaInfo : public IValueObjectMetaInfo
|
struct CValueObjectMetaInfo : public IValueObjectMetaInfo
|
||||||
@@ -73,7 +77,7 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
virtual uint getValueHash(const void *object) const override
|
virtual uint getValueHash(const void *object) const override
|
||||||
{
|
{
|
||||||
return cast(object).getValueHash();
|
return qHash(cast(object));
|
||||||
}
|
}
|
||||||
virtual int getMetaTypeId() const override
|
virtual int getMetaTypeId() const override
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ namespace BlackMisc
|
|||||||
//! Construct a variant from the given type and opaque pointer.
|
//! Construct a variant from the given type and opaque pointer.
|
||||||
CVariant(int typeId, const void *copy) : m_v(typeId, copy) {}
|
CVariant(int typeId, const void *copy) : m_v(typeId, copy) {}
|
||||||
|
|
||||||
//! \copydoc CValueObject::getValueHash
|
//! \copydoc CValueObject::qHash
|
||||||
virtual uint getValueHash() const override;
|
friend uint qHash(const CVariant &var) { return var.getValueHash(); }
|
||||||
|
|
||||||
//! Change the internal QVariant.
|
//! Change the internal QVariant.
|
||||||
void reset(const QVariant &var) { m_v = var; }
|
void reset(const QVariant &var) { m_v = var; }
|
||||||
@@ -219,6 +219,7 @@ namespace BlackMisc
|
|||||||
const void *data() const { return m_v.data(); }
|
const void *data() const { return m_v.data(); }
|
||||||
|
|
||||||
static int compareImpl(const CVariant &, const CVariant &);
|
static int compareImpl(const CVariant &, const CVariant &);
|
||||||
|
uint getValueHash() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Compare stored value of CVariant with any CValueObject derived class.
|
//! Compare stored value of CVariant with any CValueObject derived class.
|
||||||
|
|||||||
@@ -100,14 +100,14 @@ namespace BlackMiscTest
|
|||||||
QVERIFY2(station1 != vmNoWildcard, "Station should not be equal to empty list");
|
QVERIFY2(station1 != vmNoWildcard, "Station should not be equal to empty list");
|
||||||
QVERIFY2(station1 == vm, "Controller should match");
|
QVERIFY2(station1 == vm, "Controller should match");
|
||||||
QVERIFY2(vmWildcard == vmCopy, "Maps should be equal");
|
QVERIFY2(vmWildcard == vmCopy, "Maps should be equal");
|
||||||
QVERIFY2(vmWildcard.getValueHash() == vmCopy.getValueHash(), "Hashs should be equal (simple)");
|
QVERIFY2(qHash(vmWildcard) == qHash(vmCopy), "Hashs should be equal (simple)");
|
||||||
|
|
||||||
vm.addValue(CAtcStation::IndexFrequency, CFrequency(118.7, CFrequencyUnit::MHz()));
|
vm.addValue(CAtcStation::IndexFrequency, CFrequency(118.7, CFrequencyUnit::MHz()));
|
||||||
vm.addValue(CAtcStation::IndexPosition, geoPos);
|
vm.addValue(CAtcStation::IndexPosition, geoPos);
|
||||||
vmCopy = vm;
|
vmCopy = vm;
|
||||||
QVERIFY2(vm.getValueHash() == vmCopy.getValueHash(), "Hashs should be equal (detailed)");
|
QVERIFY2(qHash(vm) == qHash(vmCopy), "Hashs should be equal (detailed)");
|
||||||
vmCopy.setWildcard(!vm.isWildcard());
|
vmCopy.setWildcard(!vm.isWildcard());
|
||||||
QVERIFY2(vm.getValueHash() != vmCopy.getValueHash(), "Hashs should not be equal (detailed)");
|
QVERIFY2(qHash(vm) != qHash(vmCopy), "Hashs should not be equal (detailed)");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
Reference in New Issue
Block a user