Better_Software_Header_MobileBetter_Software_Header_Web

Find what you need - explore our website and developer resources

How to declare a qHash overload

namespace NS {

class EXPORT MyClass
{
    A m_a;
    B m_b;
    C m_c;
    D m_d;
    ~~~
};

}
#if QT_VERSION < QT_VERSION(6, 0, 0)
using qhash_result_t = uint;
#else
using qhash_result_t = size_t;
#endif
namespace NS {

// 1. add a forward declaration for the class
class MyClass;

// 2. consume the forward declaration for the class, by
// forward declaring its qHash overload
EXPORT qhash_result_t qHash(const MyClass &c, qhash_result_t seed = 0) noexcept;

class EXPORT MyClass
{
    ~~~ // same as before

    // 3. add:
    friend EXPORT qhash_result_t qHash(const MyClass &c, qhash_result_t seed) noexcept;
};

}
bool operator==(const MyClass &lhs, const MyClass &rhs) noexcept
{
    return
        lhs.a == rhs.a &&
        lhs.b == rhs.b && ~~~;
}
qhash_result_t qHash(const MyClass &c, qhash_result_t seed) noexcept
{
    QtPrivate::QHashCombine hash;

    seed = hash(seed, c.a);
    seed = hash(seed, c.b);
    seed = hash(seed, c.c);
    ~~~
    return seed;
}
qhash_result_t qHash(const MyClass &c, qhash_result_t seed) noexcept
{
    return qHashMulti(seed, c.a, c.b, ~~~);
}
inline size_t qHash(const QQuickShapeGradientCacheKey &v, uint seed = 0)
{
    uint h = seed + v.spread;
    for (int i = 0; i < 3 && i < v.stops.count(); ++i)
        h += v.stops[i].second.rgba();
    return h;
}
inline size_t qHash(const QV4Debugger::BreakPoint &b, uint seed = 0) Q_DECL_NOTHROW
{
    return qHash(b.fileName, seed) ^ b.lineNumber;
}
inline size_t qHash(const QQuickPixmapKey &key)
{
    return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.frame*23) ^
            (key.region->x()*29) ^ (key.region->y()*31) ^ (key.options.autoTransform() * 0x5c5c5c5c);
}
inline bool operator==(const QQuickPixmapKey &lhs, const QQuickPixmapKey &rhs)
{
    return *lhs.region == *rhs.region && *lhs.size == *rhs.size && *lhs.url == *rhs.url &&
            lhs.options == rhs.options && lhs.frame == rhs.frame;
}
size_t qHash(const QQuickTextNodeEngine::BinaryTreeNodeKey &key)
{
    return qHash(qMakePair(key.fontEngine, qMakePair(key.clipNode,
                                                     qMakePair(key.color, key.selectionState))));
}
// not in namespace std
qhash_result_t qHash(const std::foo &foo, qhash_result_t seed = 0)
{
    return ~~~;
}
QHash<std::foo, bar> h;
h.insert(~~~, ~~~);
struct MyStruct
{
    std::foo m_a;
    int m_b;
    ~~~
};
qhash_result_t qHash(const MyStruct &s, qhash_result_t seed = 0)
{
    // (very likely) ERROR: qHashMulti does not find qHash(std::foo)
    return qHashMulti(seed, c.m_a, c.m_b);
}
// calls f() on a T object
template <typename T> void call_f() { T t; f(t); }

struct S {};
void f(S);

void use() { call_f<S>(); }
// same as before
template <typename T> void call_f() { T t; f(t); }

#include <stdfoo>
void f(std::foo);

void use() { call_f<std::foo>(); }
// same as before
template <typename T> void call_f() { T t; f(t); }

#include <stdfoo>
namespace std {
void f(foo);
}

void use() { call_f<std::foo>(); }

About KDAB


1 Comment

30 - Jun - 2020

Marc Mutz

GiuseppeD'Angelo

Giuseppe D’Angelo

Senior Software Engineer

Learn Modern C++

Learn more