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.
  • S Offline
    S Offline
    SeDi
    wrote on 26 Nov 2018, 11:52 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...

    R 1 Reply Last reply 26 Nov 2018, 12:05
    0
    • S SeDi
      26 Nov 2018, 11:52

      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...

      R Offline
      R Offline
      raven-worx
      Moderators
      wrote on 26 Nov 2018, 12:05 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
      • S Offline
        S Offline
        sierdzio
        Moderators
        wrote on 26 Nov 2018, 12:07 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
        • S Offline
          S Offline
          SeDi
          wrote on 26 Nov 2018, 12:12 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
          • V Offline
            V Offline
            VRonin
            wrote on 26 Nov 2018, 16:59 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

            S 1 Reply Last reply 26 Nov 2018, 22:34
            1
            • V VRonin
              26 Nov 2018, 16:59

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

              S Offline
              S Offline
              SeDi
              wrote on 26 Nov 2018, 22:34 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).

              V 1 Reply Last reply 27 Nov 2018, 08:30
              0
              • S SeDi
                26 Nov 2018, 22:34

                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).

                V Offline
                V Offline
                VRonin
                wrote on 27 Nov 2018, 08:30 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

                1/7

                26 Nov 2018, 11:52

                • Login

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