Thibel
Thibel

Reputation: 297

QObject::connect: Cannot queue arguments of type 'int&'

I tried to do this :

connect(this, SIGNAL(signalClicked(int&)),  classA, SLOT(doWork(int&)));

But I get the message in the title. So I've explored the internet and I came up with this solution which is not working either:

 qRegisterMetaType<int&>("Type");
 connect(this, SIGNAL(signalClicked(Type)),  classA, SLOT(doWork(Type)));

Error: no matching function for call to ‘qRegisterMetaType(const char[5])’

Any solutions?

Upvotes: 18

Views: 35962

Answers (2)

Alexis Wilke
Alexis Wilke

Reputation: 20741

I wanted to be able to connect an event with an std::shared_ptr<>. What I have done is create a structure with that pointer and the structure is what I declare and use to send the event.

So I have an object like so:

class project
{
    typedef std::shared_ptr<project> pointer_t;

    ...
};

I need to call the Q_DECLARE_METATYPE() to pass the smart pointer. So my first idea:

Q_DECLARE_METATYPE(builder::project::pointer_t)

That did not work at all. So instead what I had to do is create a structure with that pointer and created that outside of the namespace (builder above):

// outside my namespace
struct project_ptr
{
    builder::project::pointer_t f_ptr = builder::project::pointer_t();

private:
    Q_GADGET
};

Q_DECLARE_METATYPE(project_ptr);

Then in my main class (a QWindow) I have a function to emit the signal, the actual signal, and a slot to process the message:

class snap_builder
    : public QMainWindow
    , private Ui::snap_builder
{
private:
    Q_OBJECT

public:
    ...
    void     project_changed(project::pointer_t p);

signals:
    void     projectChanged(project_ptr p);

private slots:
    void     onProjectChanged(project_ptr p);
    ...
};

As we can see, the class can include anything you want (pretty much) but the type is used by copy (no reference, no pointer).

To emit the event, I then call the project_changed() function which creates a project_ptr with the project pointer and sends that using the emit ... feature of Qt.

void snap_builder::project_changed(project::pointer_t p)
{
    project_ptr ptr;
    ptr.f_ptr = p;
    emit projectChanged(ptr);
}

Finally, you have to connect that event like so, which I do in my constructor:

connect(this, &snap_builder::projectChanged,
        this, &snap_builder::on_project_changed);

I find it rather convoluted, but that works as expected.

Upvotes: 1

Dan Milburn
Dan Milburn

Reputation: 5718

If Qt is trying to queue the arguments that means that the connection is between threads. This will not work for non-const references.

You could use a reference_wrapper to work around this, but I would strongly suggest that you reconsider your design. Passing values by reference in signal/slot connections is not a good idea.

Upvotes: 29

Related Questions