Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. qHash implementation for scoped enum type
Forum Updated to NodeBB v4.3 + New Features

qHash implementation for scoped enum type

Scheduled Pinned Locked Moved General and Desktop
qhashenum
3 Posts 2 Posters 8.9k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    apbarrero
    wrote on 24 Sept 2015, 07:11 last edited by apbarrero
    #1

    I want to have a QSet of scoped enum values within a namespace. I tried implementing a specialization of qHash function for my scoped enum type following instructions in the docs. I also checked the forum for an answer on a similar problem and the only difference is that my enum type is defined within a namespace. I'm getting an obscure compilation error I haven't been able to fully understand.

    If I define the enum in the global namespace I don't get the compilation errors, but I'd like to keep my enum defined under its namespace.

    Here's my testing program:

    #include <QCoreApplication>
    #include <QSet>
    
    namespace foo {
    namespace hash {
        enum class MyEnum
        {
            ZERO = 0
            , ONE
        };
    }
    }
    
    inline uint qHash(foo::hash::MyEnum key, uint seed)
    {
        return qHash(static_cast<uint>(key), seed);
    }
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        QSet<foo::hash::MyEnum> set;
        set.insert(foo::hash::MyEnum::ZERO);
        set.insert(foo::hash::MyEnum::ONE);
    
        return a.exec();
    }
    

    And the compilation errors:

    g++ -c -pipe -std=c++11 -g -Wall -W -D_REENTRANT -fPIC -DQT_CORE_LIB -I../hash -I. -I/opt/Qt/5.4/gcc_64/include -I/opt/Qt/5.4/gcc_64/include/QtCore -I. -I/opt/Qt/5.4/gcc_64/mkspecs/linux-g++ -o main.o ../hash/main.cpp
    In file included from /opt/Qt/5.4/gcc_64/include/QtCore/qglobal.h:70:0,
                     from /opt/Qt/5.4/gcc_64/include/QtCore/qcoreapplication.h:37,
                     from /opt/Qt/5.4/gcc_64/include/QtCore/QCoreApplication:1,
                     from ../hash/main.cpp:1:
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h: In instantiation of 'uint qHash(const T&, uint) [with T = foo::hash::MyEnum; uint = unsigned int]':
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:912:32:   required from 'QHash<Key, T>::Node** QHash<Key, T>::findNode(const Key&, uint*) const [with Key = foo::hash::MyEnum; T = QHashDummyValue; QHash<Key, T>::Node = QHashNode<foo::hash::MyEnum, QHashDummyValue>; uint = unsigned int]'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:768:36:   required from 'QHash<Key, T>::iterator QHash<Key, T>::insert(const Key&, const T&) [with Key = foo::hash::MyEnum; T = QHashDummyValue]'
    /opt/Qt/5.4/gcc_64/include/QtCore/qset.h:188:94:   required from 'QSet<T>::iterator QSet<T>::insert(const T&) [with T = foo::hash::MyEnum]'
    ../hash/main.cpp:24:39:   required from here
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:101:42: error: no matching function for call to 'qHash(const foo::hash::MyEnum&)'
         Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))
                                              ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qcompilerdetection.h:977:43: note: in definition of macro 'Q_DECL_NOEXCEPT_EXPR'
     # define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x)
                                               ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:101:42: note: candidates are:
         Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))
                                              ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qcompilerdetection.h:977:43: note: in definition of macro 'Q_DECL_NOEXCEPT_EXPR'
     # define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x)
                                               ^
    In file included from /opt/Qt/5.4/gcc_64/include/QtCore/qset.h:37:0,
                     from /opt/Qt/5.4/gcc_64/include/QtCore/QSet:1,
                     from ../hash/main.cpp:2:
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:63:52: note: constexpr uint qHash(char, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:63:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'char'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:64:52: note: constexpr uint qHash(uchar, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uchar key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:64:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'uchar {aka unsigned char}'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:65:52: note: constexpr uint qHash(signed char, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(signed char key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:65:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'signed char'
    In file included from /opt/Qt/5.4/gcc_64/include/QtCore/qset.h:37:0,
                     from /opt/Qt/5.4/gcc_64/include/QtCore/QSet:1,
                     from ../hash/main.cpp:2:
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:66:52: note: constexpr uint qHash(ushort, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ushort key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:66:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'ushort {aka short unsigned int}'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:67:52: note: constexpr uint qHash(short int, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(short key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:67:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'short int'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:68:52: note: constexpr uint qHash(uint, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(uint key, uint seed = 0) Q_DECL_NOTHROW { return key ^ seed; }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:68:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'uint {aka unsigned int}'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:69:52: note: constexpr uint qHash(int, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(int key, uint seed = 0) Q_DECL_NOTHROW { return uint(key) ^ seed; }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:69:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'int'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:70:52: note: constexpr uint qHash(ulong, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(ulong key, uint seed = 0) Q_DECL_NOTHROW
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:70:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'ulong {aka long unsigned int}'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:76:52: note: constexpr uint qHash(long int, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(long key, uint seed = 0) Q_DECL_NOTHROW { return qHash(ulong(key), seed); }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:76:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'long int'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:77:52: note: constexpr uint qHash(quint64, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(quint64 key, uint seed = 0) Q_DECL_NOTHROW
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:77:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'quint64 {aka long long unsigned int}'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:81:52: note: constexpr uint qHash(qint64, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(qint64 key, uint seed = 0) Q_DECL_NOTHROW { return qHash(quint64(key), seed); }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:81:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'qint64 {aka long long int}'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:82:42: note: uint qHash(float, uint)
     Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(float key, uint seed = 0) Q_DECL_NOTHROW;
                                              ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:82:42: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'float'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:83:42: note: uint qHash(double, uint)
     Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(double key, uint seed = 0) Q_DECL_NOTHROW;
                                              ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:83:42: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'double'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:85:42: note: uint qHash(long double, uint)
     Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q_DECL_NOTHROW;
                                              ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:85:42: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'long double'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:87:52: note: constexpr uint qHash(QChar, uint)
     Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
                                                        ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:87:52: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'QChar'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:88:41: note: uint qHash(const QByteArray&, uint)
     Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
                                             ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:88:41: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'const QByteArray&'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:89:41: note: uint qHash(const QString&, uint)
     Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
                                             ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:89:41: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'const QString&'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:90:41: note: uint qHash(const QStringRef&, uint)
     Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
                                             ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:90:41: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'const QStringRef&'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:91:41: note: uint qHash(const QBitArray&, uint)
     Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
                                             ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:91:41: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'const QBitArray&'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:92:41: note: uint qHash(QLatin1String, uint)
     Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
                                             ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:92:41: note:   no known conversion for argument 1 from 'const foo::hash::MyEnum' to 'QLatin1String'
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:96:32: note: template<class T> uint qHash(const T*, uint)
     template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
                                    ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:96:32: note:   template argument deduction/substitution failed:
    In file included from /opt/Qt/5.4/gcc_64/include/QtCore/qglobal.h:70:0,
                     from /opt/Qt/5.4/gcc_64/include/QtCore/qcoreapplication.h:37,
                     from /opt/Qt/5.4/gcc_64/include/QtCore/QCoreApplication:1,
                     from ../hash/main.cpp:1:
    /opt/Qt/5.4/gcc_64/include/QtCore/qhash.h:101:42: note:   mismatched types 'const T*' and 'foo::hash::MyEnum'
         Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t)))
                                              ^
    /opt/Qt/5.4/gcc_64/include/QtCore/qcompilerdetection.h:977:43: note: in definition of macro 'Q_DECL_NOEXCEPT_EXPR'
     # define Q_DECL_NOEXCEPT_EXPR(x) noexcept(x)
                                               ^
    
    1 Reply Last reply
    0
    • A Offline
      A Offline
      apbarrero
      wrote on 24 Sept 2015, 07:25 last edited by
      #2

      I found a way to get the code compiling. Defining the qHash function within the same scope as the enum type makes it work. But I fail to see why the definition in the global namespace with the fully qualified parameter type fails to compile.

      Here's the working code:

      #include <QCoreApplication>
      #include <QSet>
      
      namespace foo {
      namespace hash {
          enum class MyEnum
          {
              ZERO = 0
              , ONE
          };
      
          inline uint qHash(MyEnum key, uint seed)
          {
              return ::qHash(static_cast<uint>(key), seed);
          }
      }
      }
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
      
          QSet<foo::hash::MyEnum> set;
          set.insert(foo::hash::MyEnum::ZERO);
          set.insert(foo::hash::MyEnum::ONE);
      
          return a.exec();
      }
      
      1 Reply Last reply
      0
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 24 Sept 2015, 21:35 last edited by
        #3

        Hi and welcome to devnet,

        Good question, however the documentation about the qHash function states that the function must be in the namespace

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1

        3/3

        24 Sept 2015, 21:35

        • Login

        • Login or register to search.
        3 out of 3
        • First post
          3/3
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved