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. C++11 scoped enums with queued connections
Forum Updated to NodeBB v4.3 + New Features

C++11 scoped enums with queued connections

Scheduled Pinned Locked Moved General and Desktop
8 Posts 2 Posters 4.6k Views 1 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.
  • H Offline
    H Offline
    hrs1
    wrote on last edited by
    #1

    [EDIT: Split from unrelated thread: http://qt-project.org/forums/viewthread/52056/ --JKSH]

    Thanks all!!

    one more thing I'm battling now:
    I wanted to use c++-11 scoped enums "enum class <typename> {};" as the type of the parameter between signals and slots (enhancing readability and validating the arguments).
    But when I switched the code (compiled and worked) from int parameters to scoped enum class parameters I got many obscure compile time errors from Qt internals about "no matching function call to qHash(const <my scoped enum type>&)".

    Following some web advice I tried adding "Q_DECLARE_METATYPE()" macros, but that didn't seem to work.

    I guess this is a problem with a very elaborate macro/template/preprocessing framework - its difficult to comprehend compiler errors.....

    Are scoped enums OK as signal/slot arguments?
    If no - is there a similar Qt enum class which would be acceptable?

    I enjoy the depth of the reference manuals in "http://doc.qt.io/qt-5":http://doc.qt.io/qt-5/ , but is there a recommended book/web site with up to date (i.e. Qt-5.4 & C++-11/14) tutorials and best practice guides

    thanks again

    1 Reply Last reply
    0
    • JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by
      #2

      [quote author="hrs1" date="1421536494"]Following some web advice I tried adding “Q_DECLARE_METATYPE()” macros, but that didn’t seem to work.[/quote]The "Q_DECLARE_METATYPE() documentation":http://doc.qt.io/qt-5/qmetatype.html#Q_DECLARE_METATYPE says (emphasis added):

      "Adding a Q_DECLARE_METATYPE() makes the type known to all template based functions, including QVariant. Note that if you intend to use the type in queued signal and slot connections or in QObject's property system, you also have to call qRegisterMetaType() since the names are resolved at runtime."

      [quote author="hrs1" date="1421536494"]is there a recommended book/web site with up to date (i.e. Qt-5.4 & C++-11/14) tutorials and best practice guides[/quote]Currently, the only Qt 5 book out there (that I know of) is http://qmlbook.org/

      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

      1 Reply Last reply
      0
      • H Offline
        H Offline
        hrs1
        wrote on last edited by
        #3

        qRegisterMetaType() doesn't seem to do the trick.

        It seems that the signal/slot mechanism generates a qHash call with a const reference to my enum class type.
        This (and other collections: QSet<enum type>) causes the compiler to complain about missing functions.

        could you try the following:
        enum class EnumTestType {
        TEST1,
        TEST2,
        TEST3
        };

        .... Qt class definition....
        signals:
        void testSignal(EnumTestType);
        public slots:
        void testSlot(EnumTestType e);

        1 Reply Last reply
        0
        • JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #4

          This worked just fine for me, on Qt 5.4.0 + MinGW 4.9.1:

          @
          // widget.h
          #include <QWidget>
          #include <QDebug>

          enum class EnumTestType {
          TEST1,
          TEST2,
          TEST3
          };
          Q_DECLARE_METATYPE(EnumTestType)

          class Widget : public QWidget
          {
          Q_OBJECT

          signals:
          void testSignal(EnumTestType);

          public slots:
          void testSlot(EnumTestType e)
          {
          qDebug() << static_cast<int>(e);
          }

          public:
          Widget(QWidget *parent = nullptr) : QWidget(parent)
          {
          connect(this, &Widget::testSignal,
          this, &Widget::testSlot,
          Qt::QueuedConnection);

              emit testSignal(EnumTestType::TEST2);
          }
          

          };
          @

          @
          // main.cpp
          #include "widget.h"
          #include <QApplication>

          int main(int argc, char *argv[])
          {
          QApplication a(argc, argv);
          Widget w;
          w.show();

          return a.exec&#40;&#41;;
          

          }
          @

          In fact, I found out that the new Qt 5 connection syntax doesn't require qRegisterMetaType(), only Q_DECLARE_METATYPE(). If I got rid of Q_DECLARE_METATYPE(), the program still compiled without any errors. The only effect was that the connection failed at runtime.

          Try:

          Clean your project, run qmake, and build again

          Post your code here

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          1 Reply Last reply
          0
          • H Offline
            H Offline
            hrs1
            wrote on last edited by
            #5

            The example code works (though when I tried it on a Linux machine I got compile time errors on the "connect" line - but that is another issue...)

            My problem was I tried to combine the enumeration in a QSet and send the set of values between the signal and slot. Actually declaring a class with a member QSet<EnumTestType>, adding a "Q_DECLARE_METATYPE" to the new class and using this class (containing the set collection of enums) as the shared parameter between the signal and the slot.

            I tried various options, but all caused a compile time error:
            C:\Qt\5.4\mingw491_32\include\QtCore\qhash.h:-1: In instantiation of 'uint qHash(const T&, uint) [with T = EnumTestType; uint = unsigned int]':

            Sending a QSet of int does work.

            Is it possible to use QSet<enum class> as a parameter to a signal (either directly or within a class)?

            If not, what would be the recommended way to send such a collection?

            I could add helper function to convert QSet<enum class> to QSet<int> before sending the signal and converting back to QSet<enum class> after receiving data in the slot - but that seems like unnecessary overhead (both syntactic and performance wise)

            1 Reply Last reply
            0
            • JKSHJ Offline
              JKSHJ Offline
              JKSH
              Moderators
              wrote on last edited by
              #6

              QSet<EnumTestType> is a completely separate type from EnumTestType. If you want to send the QSet in a signal, do

              @
              Q_DECLARE_METATYPE(QSet<EnumTestType>)
              @

              P.S. I recommend posting code instead of text descriptions. It's easier to read that way :)

              Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

              1 Reply Last reply
              0
              • H Offline
                H Offline
                hrs1
                wrote on last edited by
                #7

                I did declare the type.
                here's the code:

                enumt.h:
                @#ifndef ENUMT_H
                #define ENUMT_H

                #include <QDebug>
                #include <QSet>
                enum class EnumTestType {
                NONE,
                TEST1,
                TEST2,
                TEST3,
                COUNT
                };
                Q_DECLARE_METATYPE(EnumTestType)

                class EnumSet {
                public:
                EnumSet() {}
                EnumSet(const EnumSet& es) {enumSet = es.enumSet;}
                public:
                QSet<EnumTestType> enumSet;
                };
                Q_DECLARE_METATYPE(EnumSet)
                Q_DECLARE_METATYPE(QSet<EnumTestType>)

                QDebug operator<< (QDebug d, const EnumTestType &e);
                QDebug operator<< (QDebug d, const EnumSet &es);

                #endif // ENUMT_H@

                enumt.cpp:
                @#include "enumt.h"

                QDebug operator<< (QDebug d, const EnumTestType &e) {
                d << static_cast<int>(e);
                return d;
                }

                QDebug operator<< (QDebug d, const EnumSet &es) {
                d << "[ ";
                for (auto e : es.enumSet) {
                d << e << " ";
                }
                d << "]";
                return d;
                }
                @

                widget.h:
                @#ifndef WIDGET_H
                #define WIDGET_H

                #include <QWidget>

                #include <QWidget>
                #include <QDebug>

                #include "enumt.h"

                class Widget : public QWidget
                {
                Q_OBJECT

                signals:
                void testSignal(EnumSet);

                public slots:
                void testSlot(EnumSet eSet);

                public:
                explicit Widget(QWidget *parent = nullptr);
                };

                #endif // WIDGET_H
                @

                widget.cpp:
                @#include "widget.h"

                Widget::Widget(QWidget *parent) : QWidget(parent) {
                connect(this, &Widget::testSignal,
                this, &Widget::testSlot,
                Qt::QueuedConnection);
                EnumSet es;
                es.enumSet += EnumTestType::TEST1;
                es.enumSet += EnumTestType::TEST3;
                es.enumSet += EnumTestType::TEST1;
                emit testSignal(es);
                }

                void Widget::testSlot(EnumSet eSet) {
                qDebug() << eSet;
                }
                @

                main.cpp:
                @#include "widget.h"
                #include <QApplication>

                int main(int argc, char *argv[])
                {
                QApplication a(argc, argv);
                Widget w;
                w.show();

                return a.exec&#40;&#41;;
                

                }@

                enum.pro:
                @#-------------------------------------------------

                Project created by QtCreator 2015-01-18T22:27:06

                #-------------------------------------------------

                QT += core gui
                CONFIG += c++14
                greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

                TARGET = enum
                TEMPLATE = app

                SOURCES += main.cpp
                widget.cpp
                enumt.cpp

                HEADERS += widget.h
                enumt.h

                FORMS += widget.ui
                @

                1 Reply Last reply
                0
                • JKSHJ Offline
                  JKSHJ Offline
                  JKSH
                  Moderators
                  wrote on last edited by
                  #8

                  Signals and slots are completely irrelevant here.

                  I just realized that you can't store a scoped enum in a QSet (or std::set) by default, just like how you can't store arbitrary classes. From the "documentation":http://doc.qt.io/qt-5/qset.html#details

                  "...there must also be a global qHash() function that returns a hash value for an argument of the key's type."

                  You need to overload qHash(), just like how you overloaded QDebug::operator<<().

                  By the way, defining EnumSet as a class is unnecessary work. If you want a short name, just make a typedef:
                  @typedef QSet<EnumTestType> EnumSet@

                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                  1 Reply Last reply
                  0

                  • Login

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