refs #413 Decomposed hash-related functions of CValueObject into Mixin::HashByTuple.

This commit is contained in:
Mathew Sutcliffe
2015-04-29 01:31:19 +01:00
parent d9faa031d2
commit 2f55caf7c6
11 changed files with 67 additions and 35 deletions

View File

@@ -118,8 +118,8 @@ namespace BlackMisc
//! \copydoc CValueObject::convertFromQVariant
virtual void convertFromQVariant(const QVariant &variant) override { BlackMisc::setFromQVariant< C<T> >(&derived(), variant); }
//! \copydoc BlackMisc::CValueObject::getValueHash
virtual uint getValueHash() const override { return qHash(&derived()); }
//! Simplifies composition, returns 0 for performance
friend uint qHash(const C<T> &) { return 0; }
//! \copydoc CValueObject::toJson
virtual QJsonObject toJson() const override

View File

@@ -232,9 +232,6 @@ namespace BlackMisc
//! \copydoc CValueObject::convertFromQVariant
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
virtual QJsonObject toJson() const override
{

View File

@@ -122,6 +122,10 @@ namespace BlackMisc
}
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

View File

@@ -279,10 +279,10 @@ namespace BlackMisc
//! Unequal operator !=
bool operator != (const CMeasurementUnit &other) const;
//! \copydoc CValueObject::getValueHash
virtual uint getValueHash() const override
//! \copydoc CValueObject::qHash
friend uint qHash(const CMeasurementUnit &unit)
{
return qHash(this->getName());
return ::qHash(unit.getName());
}
//! Name such as "meter"

View File

@@ -198,8 +198,11 @@ namespace BlackMisc
//! \copydoc CValueObject::unmarshallFromDbus
virtual void unmarshallFromDbus(const QDBusArgument &argument) override;
//! \copydoc CValueObject::getValueHash
virtual uint getValueHash() const override;
//! \copydoc CValueObject::qHash
uint getValueHash() const;
//! \copydoc CValueObject::qHash
friend uint qHash(const PQ &pq) { return pq.getValueHash(); };
//! \copydoc CValueObject::toJson
virtual QJsonObject toJson() const override;

View File

@@ -137,8 +137,11 @@ namespace BlackMisc
//! Map
const QMap<CPropertyIndex, CVariant> &map() const { return this->m_values; }
//! \copydoc CValueObject::getValueHash
virtual uint getValueHash() const override;
//! Hash value
uint getValueHash() const;
//! \copydoc CValueObject::qHash
friend uint qHash(const CPropertyIndexVariantMap &vm) { return vm.getValueHash(); }
//! \copydoc CValueObject::toQVariant
virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); }

View File

@@ -110,9 +110,6 @@ namespace BlackMisc
*/
struct CValueObjectDummyBase
{
//! Value hash
static uint getValueHash() { return 0; }
//! To JSON
static QJsonObject toJson() { return {}; }
@@ -240,6 +237,36 @@ namespace BlackMisc
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 :
public Base,
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>::LessThan::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");
using HashPolicy = typename CValueObjectPolicy<Derived>::Hash;
using DBusPolicy = typename CValueObjectPolicy<Derived>::DBus;
using JsonPolicy = typename CValueObjectPolicy<Derived>::Json;
using PropertyIndexPolicy = typename CValueObjectPolicy<Derived>::PropertyIndex;
@@ -356,12 +383,6 @@ namespace BlackMisc
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:
//! Base class
using base_type = Base;
@@ -396,12 +417,6 @@ namespace BlackMisc
//! \copydoc BlackMisc::Mixin::MetaType::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
virtual QJsonObject toJson() const
{

View File

@@ -283,6 +283,11 @@ namespace BlackMisc
template <class T, class...>
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

View File

@@ -51,6 +51,10 @@ namespace BlackMisc
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.
template <typename T>
struct CValueObjectMetaInfo : public IValueObjectMetaInfo
@@ -73,7 +77,7 @@ namespace BlackMisc
}
virtual uint getValueHash(const void *object) const override
{
return cast(object).getValueHash();
return qHash(cast(object));
}
virtual int getMetaTypeId() const override
{

View File

@@ -77,8 +77,8 @@ namespace BlackMisc
//! Construct a variant from the given type and opaque pointer.
CVariant(int typeId, const void *copy) : m_v(typeId, copy) {}
//! \copydoc CValueObject::getValueHash
virtual uint getValueHash() const override;
//! \copydoc CValueObject::qHash
friend uint qHash(const CVariant &var) { return var.getValueHash(); }
//! Change the internal QVariant.
void reset(const QVariant &var) { m_v = var; }
@@ -219,6 +219,7 @@ namespace BlackMisc
const void *data() const { return m_v.data(); }
static int compareImpl(const CVariant &, const CVariant &);
uint getValueHash() const;
};
//! Compare stored value of CVariant with any CValueObject derived class.