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. QSet<myEnumClass> --> no matching function for call to 'qHash(myEnumClass&)'
Forum Updated to NodeBB v4.3 + New Features

QSet<myEnumClass> --> no matching function for call to 'qHash(myEnumClass&)'

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 4 Posters 4.3k 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.
  • SeDiS Offline
    SeDiS Offline
    SeDi
    wrote on last edited by
    #1

    Hi and thanks for reading,
    I have an enum class Operator::OperatorType that I want o use a QSet of. It's defined in the QObject-derived class Operator:

    #include "expression.h"
    class Operator: public Expression
    {
        Q_OBJECT
    public:
    
        enum class OperatorType {
            UNDEFINED,
            ADD, // add first to second
            SUB, // substract second from first
            MUL, // multiply first by second
            DIV, // divide first by second
            SQT, // secondth root of first
            SQU  // first to the power of second
        };
        Q_ENUM(OperatorType)
        //QHASH_FOR_CLASS_ENUM(OperatorType) // Ok
        Operator(OperatorType type, QSharedPointer<Expression> first, QSharedPointer<Expression> second);
    

    At another point in my code I try to build a QSet of this type:

        QSet<Operator::OperatorType> testTypes;
        Operator::OperatorType t = Operator::OperatorType::ADD;
        testTypes.insert(t);     // <--- Error points to this line
    

    This results in the following build error:

    C:\Qt\5.11.2\mingw53_32\include\QtCore\qhashfunctions.h:112: error: no matching function for call to 'qHash(const Operator::OperatorType&)'
         Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) // error points to (t)
    

    As you can see (commented out in the above code), I have tried this idea:

    #define QHASH_FRIEND_FOR_CLASS_ENUM(T) \
    friend uint qHash(const T&, uint seed);
    
    #define QHASH_FOR_CLASS_ENUM(T) \
    inline uint qHash(const T &t, uint seed) { \
        return ::qHash(static_cast<typename std::underlying_type<T>::type>(t), seed); \
    } 
    

    Unfortuntely the problem remained. Am I doing something stupid? I'd not have thought it to be problematic, having a set of enums….

    What else would be recommendable? I'd rather not wrap the enum in a QVariant or attach it to a dummy object...

    raven-worxR 1 Reply Last reply
    0
    • SeDiS SeDi

      Hi and thanks for reading,
      I have an enum class Operator::OperatorType that I want o use a QSet of. It's defined in the QObject-derived class Operator:

      #include "expression.h"
      class Operator: public Expression
      {
          Q_OBJECT
      public:
      
          enum class OperatorType {
              UNDEFINED,
              ADD, // add first to second
              SUB, // substract second from first
              MUL, // multiply first by second
              DIV, // divide first by second
              SQT, // secondth root of first
              SQU  // first to the power of second
          };
          Q_ENUM(OperatorType)
          //QHASH_FOR_CLASS_ENUM(OperatorType) // Ok
          Operator(OperatorType type, QSharedPointer<Expression> first, QSharedPointer<Expression> second);
      

      At another point in my code I try to build a QSet of this type:

          QSet<Operator::OperatorType> testTypes;
          Operator::OperatorType t = Operator::OperatorType::ADD;
          testTypes.insert(t);     // <--- Error points to this line
      

      This results in the following build error:

      C:\Qt\5.11.2\mingw53_32\include\QtCore\qhashfunctions.h:112: error: no matching function for call to 'qHash(const Operator::OperatorType&)'
           Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(t))) // error points to (t)
      

      As you can see (commented out in the above code), I have tried this idea:

      #define QHASH_FRIEND_FOR_CLASS_ENUM(T) \
      friend uint qHash(const T&, uint seed);
      
      #define QHASH_FOR_CLASS_ENUM(T) \
      inline uint qHash(const T &t, uint seed) { \
          return ::qHash(static_cast<typename std::underlying_type<T>::type>(t), seed); \
      } 
      

      Unfortuntely the problem remained. Am I doing something stupid? I'd not have thought it to be problematic, having a set of enums….

      What else would be recommendable? I'd rather not wrap the enum in a QVariant or attach it to a dummy object...

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @SeDi
      move the definition of qHash() outside the class.

      As the error says, it is looking for qHash(const Operator::OperatorType&), not Operator::qHash(const OperatorType&)

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      1
      • sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by
        #3

        To add to @raven-worx, here is the documentation on how to implement custom qHash.

        (Z(:^

        1 Reply Last reply
        1
        • SeDiS Offline
          SeDiS Offline
          SeDi
          wrote on last edited by
          #4

          Aaaaah…. Yess… I didn't see that. Works perfectly now. Thank you so much, raven-worx and sierdzio!

          1 Reply Last reply
          0
          • VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by
            #5

            Are you sure you want to use QSet? QFlags seems more appropriate for enum values

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            SeDiS 1 Reply Last reply
            1
            • VRoninV VRonin

              Are you sure you want to use QSet? QFlags seems more appropriate for enum values

              SeDiS Offline
              SeDiS Offline
              SeDi
              wrote on last edited by SeDi
              #6

              Thank you for the idea @VRonin - I have looked into QFlags and I'd actually prefer that. But, at some point, I have to iterate over the enums stored inside - I haven't yet found a way to iterate over QFlags.

              What I actually try to achieve with the iteration (and it does work with QSet now) is to randomly select one of those enums.

              I don't want to rely on the QSet as being un-sorted in a random manner, so I pick a number by random and iterate to it:

                  int number = qrand() % types.count();
                  QSetIterator<Operator::OperatorType> iter(types);
                  int i = 0;
                  while (iter.hasNext()) {
                      if (i == number) {
                          return(iter.peekNext());
                      }
                      i++;
                      iter.next();
                  }
                  return Operator::OperatorType::UNDEFINED;
              

              With QFlags I'd probably have to resort to some even uglier bitwise operators, I'd presume (without having given it too much thought).

              VRoninV 1 Reply Last reply
              0
              • SeDiS SeDi

                Thank you for the idea @VRonin - I have looked into QFlags and I'd actually prefer that. But, at some point, I have to iterate over the enums stored inside - I haven't yet found a way to iterate over QFlags.

                What I actually try to achieve with the iteration (and it does work with QSet now) is to randomly select one of those enums.

                I don't want to rely on the QSet as being un-sorted in a random manner, so I pick a number by random and iterate to it:

                    int number = qrand() % types.count();
                    QSetIterator<Operator::OperatorType> iter(types);
                    int i = 0;
                    while (iter.hasNext()) {
                        if (i == number) {
                            return(iter.peekNext());
                        }
                        i++;
                        iter.next();
                    }
                    return Operator::OperatorType::UNDEFINED;
                

                With QFlags I'd probably have to resort to some even uglier bitwise operators, I'd presume (without having given it too much thought).

                VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #7
                enum OperatorType {
                        UNDEFINED = 0,
                        ADD = 0x1, // add first to second
                        SUB = 0x2, // substract second from first
                        MUL= 0x4, // multiply first by second
                        DIV= 0x8, // divide first by second
                        SQT= 0x10, // secondth root of first
                        SQU =0x20   // first to the power of second
                    };
                Q_FLAG(OperatorType)
                

                But, at some point, I have to iterate over the enums stored inside

                const auto flagMeta = QMetaEnum::fromType<Operator::OperatorType>();
                    for(int i=0;i<flagMeta.keyCount();++i){
                        qDebug() << flagMeta.key(i) << ": " << flagMeta.value(i);
                    }
                

                even uglier bitwise operators

                const auto flagMeta = QMetaEnum::fromType<Operator::OperatorType>();
                const auto randomOperator = static_cast<Operator::OperatorType>(1 << (qrand() % (flagMeta.keyCount()-1)));
                

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                3

                • Login

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